@partylayer/registry-client 0.2.2 → 0.2.4
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/LICENSE +1 -1
- package/README.md +62 -0
- package/dist/index.d.mts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +78 -67
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +78 -67
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
package/LICENSE
CHANGED
package/README.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# @partylayer/registry-client
|
|
2
|
+
|
|
3
|
+
<div align="center">
|
|
4
|
+
|
|
5
|
+
**Wallet registry client for PartyLayer**
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/@partylayer/registry-client)
|
|
8
|
+
[](https://www.typescriptlang.org/)
|
|
9
|
+
[](https://opensource.org/licenses/MIT)
|
|
10
|
+
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Overview
|
|
16
|
+
|
|
17
|
+
`@partylayer/registry-client` fetches and validates the Canton Network wallet registry. It provides wallet metadata (names, icons, install URLs) with integrity verification and caching.
|
|
18
|
+
|
|
19
|
+
### Features
|
|
20
|
+
|
|
21
|
+
- **Signed Registry**: Verifies registry signature to prevent tampering
|
|
22
|
+
- **Automatic Caching**: Reduces network requests with configurable TTL
|
|
23
|
+
- **Schema Validation**: Ensures registry entries match expected format
|
|
24
|
+
- **Stale Fallback**: Uses cached data when network is unavailable
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Installation
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm install @partylayer/registry-client
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
> **Note**: Most dApp developers should use `@partylayer/sdk` instead, which includes the registry client automatically.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Usage
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
import { RegistryClient } from '@partylayer/registry-client';
|
|
42
|
+
|
|
43
|
+
const registry = new RegistryClient({
|
|
44
|
+
url: 'https://registry.partylayer.xyz/v1/wallets.json',
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const wallets = await registry.getWallets();
|
|
48
|
+
// [{ id: 'console', name: 'Console Wallet', icon: '...', ... }, ...]
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Links
|
|
54
|
+
|
|
55
|
+
- [GitHub Repository](https://github.com/PartyLayer/PartyLayer)
|
|
56
|
+
- [Report Issues](https://github.com/PartyLayer/PartyLayer/issues)
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## License
|
|
61
|
+
|
|
62
|
+
MIT
|
package/dist/index.d.mts
CHANGED
|
@@ -211,6 +211,8 @@ interface RegistryClientOptions {
|
|
|
211
211
|
enableCache?: boolean;
|
|
212
212
|
/** Custom fetch function */
|
|
213
213
|
fetch?: typeof fetch;
|
|
214
|
+
/** Fetch timeout in milliseconds (default: 8000) */
|
|
215
|
+
fetchTimeout?: number;
|
|
214
216
|
/** Storage adapter for persistent cache */
|
|
215
217
|
storage?: {
|
|
216
218
|
get(key: string): Promise<string | null>;
|
|
@@ -229,6 +231,7 @@ declare class RegistryClient {
|
|
|
229
231
|
private staleTtl;
|
|
230
232
|
private enableCache;
|
|
231
233
|
private fetchFn;
|
|
234
|
+
private fetchTimeout;
|
|
232
235
|
private storage?;
|
|
233
236
|
private memoryCache;
|
|
234
237
|
private currentStatus;
|
package/dist/index.d.ts
CHANGED
|
@@ -211,6 +211,8 @@ interface RegistryClientOptions {
|
|
|
211
211
|
enableCache?: boolean;
|
|
212
212
|
/** Custom fetch function */
|
|
213
213
|
fetch?: typeof fetch;
|
|
214
|
+
/** Fetch timeout in milliseconds (default: 8000) */
|
|
215
|
+
fetchTimeout?: number;
|
|
214
216
|
/** Storage adapter for persistent cache */
|
|
215
217
|
storage?: {
|
|
216
218
|
get(key: string): Promise<string | null>;
|
|
@@ -229,6 +231,7 @@ declare class RegistryClient {
|
|
|
229
231
|
private staleTtl;
|
|
230
232
|
private enableCache;
|
|
231
233
|
private fetchFn;
|
|
234
|
+
private fetchTimeout;
|
|
232
235
|
private storage?;
|
|
233
236
|
private memoryCache;
|
|
234
237
|
private currentStatus;
|
package/dist/index.js
CHANGED
|
@@ -93,6 +93,7 @@ var RegistryClient = class {
|
|
|
93
93
|
staleTtl;
|
|
94
94
|
enableCache;
|
|
95
95
|
fetchFn;
|
|
96
|
+
fetchTimeout;
|
|
96
97
|
storage;
|
|
97
98
|
// In-memory cache
|
|
98
99
|
memoryCache = {
|
|
@@ -118,6 +119,7 @@ var RegistryClient = class {
|
|
|
118
119
|
} else {
|
|
119
120
|
this.fetchFn = fetch;
|
|
120
121
|
}
|
|
122
|
+
this.fetchTimeout = options.fetchTimeout || 8e3;
|
|
121
123
|
this.storage = options.storage;
|
|
122
124
|
if (this.storage) {
|
|
123
125
|
this.loadFromStorage().catch(() => {
|
|
@@ -190,87 +192,96 @@ var RegistryClient = class {
|
|
|
190
192
|
const registryUrl = this.getRegistryUrl();
|
|
191
193
|
const sigUrl = this.getSignatureUrl();
|
|
192
194
|
const requireSignature = this.publicKeys.length > 0;
|
|
193
|
-
const
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
195
|
+
const controller = new AbortController();
|
|
196
|
+
const timeoutId = setTimeout(() => controller.abort(), this.fetchTimeout);
|
|
197
|
+
try {
|
|
198
|
+
const registryResponse = await this.fetchFn(registryUrl, {
|
|
199
|
+
headers: {
|
|
200
|
+
"Accept": "application/json",
|
|
201
|
+
"If-None-Match": this.memoryCache.lastKnownGood?.etag || ""
|
|
202
|
+
},
|
|
203
|
+
signal: controller.signal
|
|
204
|
+
});
|
|
205
|
+
if (registryResponse.status === 304) {
|
|
206
|
+
if (this.memoryCache.lastKnownGood) {
|
|
207
|
+
let signature2;
|
|
208
|
+
if (requireSignature) {
|
|
209
|
+
try {
|
|
210
|
+
const sigResponse = await this.fetchFn(sigUrl, {
|
|
211
|
+
headers: { "Accept": "application/json" },
|
|
212
|
+
signal: controller.signal
|
|
213
|
+
});
|
|
214
|
+
if (sigResponse.ok) {
|
|
215
|
+
signature2 = JSON.parse(await sigResponse.text());
|
|
216
|
+
} else {
|
|
217
|
+
signature2 = { algorithm: "ed25519", signature: "", keyFingerprint: "", signedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
218
|
+
}
|
|
219
|
+
} catch {
|
|
210
220
|
signature2 = { algorithm: "ed25519", signature: "", keyFingerprint: "", signedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
211
221
|
}
|
|
212
|
-
}
|
|
222
|
+
} else {
|
|
213
223
|
signature2 = { algorithm: "ed25519", signature: "", keyFingerprint: "", signedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
214
224
|
}
|
|
215
|
-
|
|
216
|
-
|
|
225
|
+
return {
|
|
226
|
+
registry: this.memoryCache.lastKnownGood.registry,
|
|
227
|
+
signature: signature2,
|
|
228
|
+
etag: this.memoryCache.lastKnownGood.etag
|
|
229
|
+
};
|
|
217
230
|
}
|
|
218
|
-
return {
|
|
219
|
-
registry: this.memoryCache.lastKnownGood.registry,
|
|
220
|
-
signature: signature2,
|
|
221
|
-
etag: this.memoryCache.lastKnownGood.etag
|
|
222
|
-
};
|
|
223
231
|
}
|
|
224
|
-
|
|
225
|
-
if (!registryResponse.ok) {
|
|
226
|
-
throw new core.RegistryFetchFailedError(
|
|
227
|
-
registryUrl,
|
|
228
|
-
new Error(`${registryResponse.status} ${registryResponse.statusText}`)
|
|
229
|
-
);
|
|
230
|
-
}
|
|
231
|
-
const registryJson = await registryResponse.text();
|
|
232
|
-
const registry = JSON.parse(registryJson);
|
|
233
|
-
const etag = registryResponse.headers.get("ETag") || void 0;
|
|
234
|
-
if (!validateRegistry(registry)) {
|
|
235
|
-
throw new core.RegistrySchemaInvalidError(
|
|
236
|
-
"Invalid registry schema",
|
|
237
|
-
{ url: registryUrl }
|
|
238
|
-
);
|
|
239
|
-
}
|
|
240
|
-
let signature;
|
|
241
|
-
if (requireSignature) {
|
|
242
|
-
const sigResponse = await this.fetchFn(sigUrl, {
|
|
243
|
-
headers: {
|
|
244
|
-
"Accept": "application/json"
|
|
245
|
-
}
|
|
246
|
-
});
|
|
247
|
-
if (!sigResponse.ok) {
|
|
232
|
+
if (!registryResponse.ok) {
|
|
248
233
|
throw new core.RegistryFetchFailedError(
|
|
249
|
-
|
|
250
|
-
new Error(`${
|
|
234
|
+
registryUrl,
|
|
235
|
+
new Error(`${registryResponse.status} ${registryResponse.statusText}`)
|
|
251
236
|
);
|
|
252
237
|
}
|
|
253
|
-
|
|
254
|
-
const
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
238
|
+
const registryJson = await registryResponse.text();
|
|
239
|
+
const registry = JSON.parse(registryJson);
|
|
240
|
+
const etag = registryResponse.headers.get("ETag") || void 0;
|
|
241
|
+
if (!validateRegistry(registry)) {
|
|
242
|
+
throw new core.RegistrySchemaInvalidError(
|
|
243
|
+
"Invalid registry schema",
|
|
258
244
|
{ url: registryUrl }
|
|
259
245
|
);
|
|
260
246
|
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
247
|
+
let signature;
|
|
248
|
+
if (requireSignature) {
|
|
249
|
+
const sigResponse = await this.fetchFn(sigUrl, {
|
|
250
|
+
headers: {
|
|
251
|
+
"Accept": "application/json"
|
|
252
|
+
},
|
|
253
|
+
signal: controller.signal
|
|
254
|
+
});
|
|
255
|
+
if (!sigResponse.ok) {
|
|
256
|
+
throw new core.RegistryFetchFailedError(
|
|
257
|
+
sigUrl,
|
|
258
|
+
new Error(`${sigResponse.status} ${sigResponse.statusText}`)
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
signature = JSON.parse(await sigResponse.text());
|
|
262
|
+
const verified = await this.verifyRegistrySignature(registryJson, signature);
|
|
263
|
+
if (!verified) {
|
|
264
|
+
throw new core.RegistryVerificationFailedError(
|
|
265
|
+
"Signature verification failed",
|
|
266
|
+
{ url: registryUrl }
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
} else {
|
|
270
|
+
console.log("[RegistryClient] Dev mode: skipping signature fetch (no public keys configured)");
|
|
271
|
+
signature = { algorithm: "ed25519", signature: "", keyFingerprint: "", signedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
272
|
+
}
|
|
273
|
+
if (this.memoryCache.lastKnownGood) {
|
|
274
|
+
if (registry.metadata.sequence < this.memoryCache.lastKnownGood.sequence) {
|
|
275
|
+
throw new core.RegistryVerificationFailedError(
|
|
276
|
+
`Sequence downgrade detected: ${registry.metadata.sequence} < ${this.memoryCache.lastKnownGood.sequence}`,
|
|
277
|
+
{ url: registryUrl }
|
|
278
|
+
);
|
|
279
|
+
}
|
|
271
280
|
}
|
|
281
|
+
return { registry, signature, etag };
|
|
282
|
+
} finally {
|
|
283
|
+
clearTimeout(timeoutId);
|
|
272
284
|
}
|
|
273
|
-
return { registry, signature, etag };
|
|
274
285
|
}
|
|
275
286
|
/**
|
|
276
287
|
* Get registry with SWR pattern
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/schema.ts","../src/client.ts"],"names":["toWalletId","signature","RegistryFetchFailedError","RegistrySchemaInvalidError","RegistryVerificationFailedError","WalletNotFoundError"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Wallet Registry Schema v1\n * \n * This schema defines the structure of the wallet registry JSON.\n * The registry is versioned and supports:\n * - Multiple wallet entries\n * - Versioning and rollback\n * - Integrity checks (Ed25519 signatures)\n * - Multi-channel (stable/beta)\n * - Forward compatibility\n * \n * References:\n * - Wallet Integration Guide: https://docs.digitalasset.com/integrate/devnet/index.html\n */\n\nimport type { WalletInfo, NetworkId, CapabilityKey } from '@partylayer/core';\nimport { toWalletId } from '@partylayer/core';\n\n/**\n * Registry schema version\n */\nexport const REGISTRY_SCHEMA_VERSION = '1.0.0';\n\n/**\n * Registry channel\n */\nexport type RegistryChannel = 'stable' | 'beta';\n\n/**\n * Wallet entry in registry\n */\nexport interface RegistryWalletEntry {\n /** Wallet identifier (must be unique within channel) */\n id: string;\n /** Display name */\n name: string;\n /** Short description */\n description?: string;\n /** Homepage URL */\n homepage?: string;\n /** Icon URL (should be absolute) */\n icon?: string;\n /** Supported networks */\n supportedNetworks: NetworkId[];\n /** Wallet capabilities */\n capabilities: {\n signMessage: boolean;\n signTransaction: boolean;\n submitTransaction: boolean;\n transactionStatus: boolean;\n switchNetwork: boolean;\n multiParty: boolean;\n };\n /** Adapter configuration */\n adapter: {\n /** Adapter type/name */\n type: string;\n /** Adapter-specific configuration */\n config?: Record<string, unknown>;\n };\n /** Installation detection hints */\n installation?: {\n /** Check if wallet is installed via window property */\n windowProperty?: string;\n /** Check if wallet is installed via script tag */\n scriptTag?: string;\n /** Check if wallet is installed via browser extension */\n extensionId?: string;\n };\n /** SDK version compatibility */\n sdkVersion?: string;\n /** Metadata version (for cache invalidation) */\n version?: string;\n /** Origin allowlist (optional - if present, only these origins can connect) */\n originAllowlist?: string[];\n}\n\n/**\n * Registry metadata\n */\nexport interface RegistryMetadata {\n /** Registry version (semver) */\n registryVersion: string;\n /** Schema version */\n schemaVersion: string;\n /** ISO 8601 timestamp when registry was published */\n publishedAt: string;\n /** Channel (stable or beta) */\n channel: RegistryChannel;\n /** Monotonic sequence number (increments on each update) */\n sequence: number;\n /** Registry publisher */\n publisher?: string;\n}\n\n/**\n * Wallet Registry v1 structure\n * \n * Note: Signature is NOT embedded. It's in a separate .sig file.\n */\nexport interface WalletRegistryV1 {\n /** Registry metadata */\n metadata: RegistryMetadata;\n /** Array of wallet entries */\n wallets: RegistryWalletEntry[];\n}\n\n/**\n * Registry signature file format\n * \n * This is stored separately as registry.sig\n */\nexport interface RegistrySignature {\n /** Signature algorithm (always 'ed25519') */\n algorithm: 'ed25519';\n /** Signature value (base64-encoded) */\n signature: string;\n /** Public key fingerprint (for key identification) */\n keyFingerprint: string;\n /** Timestamp when signed */\n signedAt: string;\n}\n\n/**\n * Validate registry structure\n */\nexport function validateRegistry(\n registry: unknown\n): registry is WalletRegistryV1 {\n if (typeof registry !== 'object' || registry === null) {\n return false;\n }\n\n const r = registry as Record<string, unknown>;\n\n // Check metadata\n if (!r.metadata || typeof r.metadata !== 'object') {\n return false;\n }\n\n const metadata = r.metadata as Record<string, unknown>;\n if (\n typeof metadata.registryVersion !== 'string' ||\n typeof metadata.schemaVersion !== 'string' ||\n typeof metadata.publishedAt !== 'string' ||\n typeof metadata.channel !== 'string' ||\n (metadata.channel !== 'stable' && metadata.channel !== 'beta') ||\n typeof metadata.sequence !== 'number' ||\n !Number.isInteger(metadata.sequence) ||\n metadata.sequence < 0\n ) {\n return false;\n }\n\n // Check wallets array\n if (!Array.isArray(r.wallets)) {\n return false;\n }\n\n // Validate each wallet entry\n const walletIds = new Set<string>();\n for (const wallet of r.wallets) {\n if (!validateWalletEntry(wallet)) {\n return false;\n }\n // Check uniqueness\n const entry = wallet as RegistryWalletEntry;\n if (walletIds.has(entry.id)) {\n return false;\n }\n walletIds.add(entry.id);\n }\n\n return true;\n}\n\n/**\n * Validate wallet entry\n */\nexport function validateWalletEntry(\n entry: unknown\n): entry is RegistryWalletEntry {\n if (typeof entry !== 'object' || entry === null) {\n return false;\n }\n\n const e = entry as Record<string, unknown>;\n\n return (\n typeof e.id === 'string' &&\n typeof e.name === 'string' &&\n Array.isArray(e.supportedNetworks) &&\n typeof e.capabilities === 'object' &&\n e.capabilities !== null &&\n typeof e.adapter === 'object' &&\n e.adapter !== null &&\n typeof (e.adapter as Record<string, unknown>).type === 'string' &&\n (e.originAllowlist === undefined || Array.isArray(e.originAllowlist))\n );\n}\n\n/**\n * Convert registry entry to wallet info\n */\nexport function registryEntryToWalletInfo(\n entry: RegistryWalletEntry,\n channel: RegistryChannel\n): WalletInfo {\n const capabilities: CapabilityKey[] = ['connect', 'disconnect'];\n if (entry.capabilities.signMessage) {\n capabilities.push('signMessage');\n }\n if (entry.capabilities.signTransaction) {\n capabilities.push('signTransaction');\n }\n if (entry.capabilities.submitTransaction) {\n capabilities.push('submitTransaction');\n }\n if (entry.capabilities.transactionStatus) {\n capabilities.push('events');\n }\n\n return {\n walletId: toWalletId(entry.id),\n name: entry.name,\n website: entry.homepage || '',\n icons: {\n sm: entry.icon,\n md: entry.icon,\n lg: entry.icon,\n },\n category: 'browser',\n capabilities,\n installHints: entry.installation\n ? {\n injectedKey: entry.installation.windowProperty,\n extensionId: entry.installation.extensionId,\n deepLinkScheme: entry.installation.scriptTag,\n }\n : undefined,\n adapter: {\n packageName: entry.adapter.type,\n versionRange: entry.sdkVersion || '*',\n },\n docs: entry.homepage ? [entry.homepage] : [],\n minSdkVersion: entry.sdkVersion,\n networks: entry.supportedNetworks,\n channel,\n // Store origin allowlist in metadata for SDK enforcement\n ...(entry.originAllowlist\n ? { metadata: { originAllowlist: JSON.stringify(entry.originAllowlist) } }\n : {}),\n };\n}\n\n/**\n * @deprecated Use registryEntryToWalletInfo instead\n */\nexport function registryEntryToMetadata(\n entry: RegistryWalletEntry\n): WalletInfo {\n return registryEntryToWalletInfo(entry, 'stable');\n}\n","/**\n * Registry client for fetching and caching wallet registry\n * \n * Features:\n * - Ed25519 signature verification\n * - Multi-channel support (stable/beta)\n * - Sequence number validation (prevents downgrades)\n * - Last-known-good caching\n * - SWR pattern (serve cached immediately, refresh in background)\n * - ETag support for efficient updates\n * \n * References:\n * - Wallet Integration Guide: https://docs.digitalasset.com/integrate/devnet/index.html\n */\n\nimport type { WalletInfo } from '@partylayer/core';\nimport {\n RegistryFetchFailedError,\n RegistryVerificationFailedError,\n RegistrySchemaInvalidError,\n WalletNotFoundError,\n} from '@partylayer/core';\nimport type {\n WalletRegistryV1,\n RegistryWalletEntry,\n RegistryChannel,\n RegistrySignature,\n} from './schema';\nimport {\n validateRegistry,\n validateWalletEntry,\n registryEntryToWalletInfo,\n} from './schema';\nimport type { RegistryStatus, CachedRegistry, LastFetchAttempt } from './status';\n\n/**\n * Registry client options\n */\nexport interface RegistryClientOptions {\n /** Base registry URL (client appends /v1/{channel}/registry.json) */\n registryUrl?: string;\n /** Registry channel */\n channel?: RegistryChannel;\n /** Public keys for signature verification (base64) */\n registryPublicKeys?: string[];\n /** Cache TTL in milliseconds (default: 1 hour) */\n cacheTtl?: number;\n /** Stale TTL in milliseconds (default: 24 hours - cache usable but marked stale) */\n staleTtl?: number;\n /** Enable cache (default: true) */\n enableCache?: boolean;\n /** Custom fetch function */\n fetch?: typeof fetch;\n /** Storage adapter for persistent cache */\n storage?: {\n get(key: string): Promise<string | null>;\n set(key: string, value: string): Promise<void>;\n remove(key: string): Promise<void>;\n };\n}\n\n/**\n * Default registry URL\n */\nconst DEFAULT_REGISTRY_URL = 'https://registry.partylayer.xyz';\n\n/**\n * Registry client\n */\nexport class RegistryClient {\n private baseUrl: string;\n private channel: RegistryChannel;\n private publicKeys: string[];\n private cacheTtl: number;\n private staleTtl: number;\n private enableCache: boolean;\n private fetchFn: typeof fetch;\n private storage?: RegistryClientOptions['storage'];\n\n // In-memory cache\n private memoryCache: {\n lastKnownGood: CachedRegistry | null;\n lastAttempt: LastFetchAttempt | null;\n refreshPromise: Promise<WalletRegistryV1> | null;\n } = {\n lastKnownGood: null,\n lastAttempt: null,\n refreshPromise: null,\n };\n\n // Status tracking\n private currentStatus: RegistryStatus | null = null;\n\n constructor(options: RegistryClientOptions = {}) {\n this.baseUrl = options.registryUrl || DEFAULT_REGISTRY_URL;\n this.channel = options.channel || 'stable';\n this.publicKeys = options.registryPublicKeys || [];\n this.cacheTtl = options.cacheTtl || 60 * 60 * 1000; // 1 hour\n this.staleTtl = options.staleTtl || 24 * 60 * 60 * 1000; // 24 hours\n this.enableCache = options.enableCache !== false;\n // Bind fetch to prevent \"Illegal invocation\" error\n // Use global fetch directly to avoid context issues\n if (options.fetch) {\n this.fetchFn = options.fetch;\n } else if (typeof window !== 'undefined' && window.fetch) {\n this.fetchFn = window.fetch.bind(window);\n } else if (typeof globalThis !== 'undefined' && globalThis.fetch) {\n this.fetchFn = globalThis.fetch.bind(globalThis);\n } else {\n this.fetchFn = fetch;\n }\n this.storage = options.storage;\n\n // Load from persistent storage if available\n if (this.storage) {\n this.loadFromStorage().catch(() => {\n // Ignore errors on load\n });\n }\n }\n\n /**\n * Get registry URL for channel\n */\n private getRegistryUrl(): string {\n return `${this.baseUrl}/v1/${this.channel}/registry.json`;\n }\n\n /**\n * Get signature URL for channel\n */\n private getSignatureUrl(): string {\n return `${this.baseUrl}/v1/${this.channel}/registry.sig`;\n }\n\n /**\n * Import public key from base64\n */\n private async importPublicKey(keyBase64: string): Promise<CryptoKey> {\n const keyBuffer = Buffer.from(keyBase64, 'base64');\n return await crypto.subtle.importKey(\n 'raw',\n keyBuffer,\n {\n name: 'Ed25519',\n namedCurve: 'Ed25519',\n },\n true,\n ['verify']\n );\n }\n\n /**\n * Verify signature\n */\n private async verifySignature(\n registryJson: string,\n signature: RegistrySignature,\n publicKey: CryptoKey\n ): Promise<boolean> {\n if (signature.algorithm !== 'ed25519') {\n return false;\n }\n\n const data = new TextEncoder().encode(registryJson);\n const sigBuffer = Buffer.from(signature.signature, 'base64');\n return await crypto.subtle.verify('Ed25519', publicKey, sigBuffer, data);\n }\n\n /**\n * Verify registry signature\n */\n private async verifyRegistrySignature(\n registryJson: string,\n signature: RegistrySignature\n ): Promise<boolean> {\n if (this.publicKeys.length === 0) {\n // No public keys configured - skip verification (dev mode)\n return true;\n }\n\n // Try each public key\n for (const pubkeyBase64 of this.publicKeys) {\n try {\n const publicKey = await this.importPublicKey(pubkeyBase64);\n const isValid = await this.verifySignature(registryJson, signature, publicKey);\n if (isValid) {\n return true;\n }\n } catch {\n // Try next key\n continue;\n }\n }\n\n return false;\n }\n\n /**\n * Fetch registry and signature from network\n */\n private async fetchFromNetwork(): Promise<{\n registry: WalletRegistryV1;\n signature: RegistrySignature;\n etag?: string;\n }> {\n const registryUrl = this.getRegistryUrl();\n const sigUrl = this.getSignatureUrl();\n const requireSignature = this.publicKeys.length > 0;\n\n // Fetch registry (always required)\n const registryResponse = await this.fetchFn(registryUrl, {\n headers: {\n 'Accept': 'application/json',\n 'If-None-Match': this.memoryCache.lastKnownGood?.etag || '',\n },\n });\n\n // Handle 304 Not Modified\n if (registryResponse.status === 304) {\n if (this.memoryCache.lastKnownGood) {\n // For 304, we still need a signature object for return type\n // In dev mode, create dummy signature (skip fetch entirely)\n let signature: RegistrySignature;\n if (requireSignature) {\n // Production mode: try to fetch signature\n try {\n const sigResponse = await this.fetchFn(sigUrl, {\n headers: { 'Accept': 'application/json' },\n });\n if (sigResponse.ok) {\n signature = JSON.parse(await sigResponse.text()) as RegistrySignature;\n } else {\n // Signature missing but we have cache - use dummy\n signature = { algorithm: 'ed25519', signature: '', keyFingerprint: '', signedAt: new Date().toISOString() };\n }\n } catch {\n signature = { algorithm: 'ed25519', signature: '', keyFingerprint: '', signedAt: new Date().toISOString() };\n }\n } else {\n // Dev mode: create dummy signature\n signature = { algorithm: 'ed25519', signature: '', keyFingerprint: '', signedAt: new Date().toISOString() };\n }\n \n return {\n registry: this.memoryCache.lastKnownGood.registry,\n signature,\n etag: this.memoryCache.lastKnownGood.etag,\n };\n }\n }\n\n if (!registryResponse.ok) {\n throw new RegistryFetchFailedError(\n registryUrl,\n new Error(`${registryResponse.status} ${registryResponse.statusText}`)\n );\n }\n\n const registryJson = await registryResponse.text();\n const registry = JSON.parse(registryJson) as WalletRegistryV1;\n const etag = registryResponse.headers.get('ETag') || undefined;\n\n // Validate schema\n if (!validateRegistry(registry)) {\n throw new RegistrySchemaInvalidError(\n 'Invalid registry schema',\n { url: registryUrl }\n );\n }\n\n // Fetch signature (skip entirely in dev mode when no public keys)\n let signature: RegistrySignature;\n \n if (requireSignature) {\n // Public keys configured - signature is required\n const sigResponse = await this.fetchFn(sigUrl, {\n headers: {\n 'Accept': 'application/json',\n },\n });\n\n if (!sigResponse.ok) {\n throw new RegistryFetchFailedError(\n sigUrl,\n new Error(`${sigResponse.status} ${sigResponse.statusText}`)\n );\n }\n signature = JSON.parse(await sigResponse.text()) as RegistrySignature;\n \n // Verify signature\n const verified = await this.verifyRegistrySignature(registryJson, signature);\n if (!verified) {\n throw new RegistryVerificationFailedError(\n 'Signature verification failed',\n { url: registryUrl }\n );\n }\n } else {\n // Dev mode: skip signature fetch entirely, create dummy signature\n console.log('[RegistryClient] Dev mode: skipping signature fetch (no public keys configured)');\n signature = { algorithm: 'ed25519', signature: '', keyFingerprint: '', signedAt: new Date().toISOString() };\n }\n\n // Check sequence number (prevent downgrades)\n if (this.memoryCache.lastKnownGood) {\n if (registry.metadata.sequence < this.memoryCache.lastKnownGood.sequence) {\n throw new RegistryVerificationFailedError(\n `Sequence downgrade detected: ${registry.metadata.sequence} < ${this.memoryCache.lastKnownGood.sequence}`,\n { url: registryUrl }\n );\n }\n }\n\n return { registry, signature, etag };\n }\n\n /**\n * Get registry with SWR pattern\n * - Returns cached immediately if available\n * - Refreshes in background\n */\n async getRegistry(): Promise<WalletRegistryV1> {\n // Return cached immediately if available\n if (this.memoryCache.lastKnownGood) {\n const now = Date.now();\n const age = now - this.memoryCache.lastKnownGood.fetchedAt;\n\n // If cache is fresh, return it\n if (age < this.cacheTtl) {\n // Trigger background refresh if not already refreshing\n if (!this.memoryCache.refreshPromise) {\n this.memoryCache.refreshPromise = this.refreshRegistry();\n }\n return this.memoryCache.lastKnownGood.registry;\n }\n\n // Cache is stale but usable\n if (age < this.staleTtl) {\n // Trigger refresh\n if (!this.memoryCache.refreshPromise) {\n this.memoryCache.refreshPromise = this.refreshRegistry();\n }\n return this.memoryCache.lastKnownGood.registry;\n }\n }\n\n // No cache or too stale - fetch synchronously\n return await this.refreshRegistry();\n }\n\n /**\n * Refresh registry from network\n */\n private async refreshRegistry(): Promise<WalletRegistryV1> {\n // If already refreshing, wait for that\n if (this.memoryCache.refreshPromise) {\n return await this.memoryCache.refreshPromise;\n }\n\n const refreshPromise = (async () => {\n try {\n const { registry, etag } = await this.fetchFromNetwork();\n\n console.log('[RegistryClient] Successfully fetched registry:', {\n channel: registry.metadata.channel,\n sequence: registry.metadata.sequence,\n walletCount: registry.wallets.length,\n });\n\n // Update cache\n const cached: CachedRegistry = {\n registry,\n verified: true,\n fetchedAt: Date.now(),\n etag,\n sequence: registry.metadata.sequence,\n };\n\n this.memoryCache.lastKnownGood = cached;\n this.memoryCache.lastAttempt = {\n fetchedAt: Date.now(),\n };\n\n // Update status\n this.updateStatus({\n source: 'network',\n verified: true,\n channel: registry.metadata.channel,\n sequence: registry.metadata.sequence,\n stale: false,\n fetchedAt: cached.fetchedAt,\n etag,\n });\n\n // Persist to storage\n if (this.storage) {\n await this.saveToStorage(cached);\n }\n\n return registry;\n } catch (error) {\n // Update last attempt\n this.memoryCache.lastAttempt = {\n fetchedAt: Date.now(),\n errorCode:\n error instanceof RegistryFetchFailedError\n ? 'REGISTRY_FETCH_FAILED'\n : error instanceof RegistryVerificationFailedError\n ? 'REGISTRY_VERIFICATION_FAILED'\n : error instanceof RegistrySchemaInvalidError\n ? 'REGISTRY_SCHEMA_INVALID'\n : 'UNKNOWN',\n };\n\n // Update status with error\n const lastKnownGood = this.memoryCache.lastKnownGood;\n if (lastKnownGood) {\n const cantonError = error instanceof RegistryFetchFailedError ||\n error instanceof RegistryVerificationFailedError ||\n error instanceof RegistrySchemaInvalidError\n ? error\n : undefined;\n this.updateStatus({\n source: 'cache',\n verified: lastKnownGood.verified,\n channel: lastKnownGood.registry.metadata.channel,\n sequence: lastKnownGood.sequence,\n stale: Date.now() - lastKnownGood.fetchedAt > this.cacheTtl,\n fetchedAt: lastKnownGood.fetchedAt,\n etag: lastKnownGood.etag,\n error: cantonError,\n });\n\n // Return last known good\n return lastKnownGood.registry;\n }\n\n // No cache available - rethrow\n throw error;\n } finally {\n this.memoryCache.refreshPromise = null;\n }\n })();\n\n this.memoryCache.refreshPromise = refreshPromise;\n return await refreshPromise;\n }\n\n /**\n * Update registry status\n */\n private updateStatus(status: RegistryStatus): void {\n this.currentStatus = status;\n }\n\n /**\n * Get current registry status\n */\n getStatus(): RegistryStatus | null {\n if (!this.memoryCache.lastKnownGood) {\n return null;\n }\n\n const now = Date.now();\n const age = now - this.memoryCache.lastKnownGood.fetchedAt;\n\n return {\n source: this.currentStatus?.source || 'cache',\n verified: this.memoryCache.lastKnownGood.verified,\n channel: this.memoryCache.lastKnownGood.registry.metadata.channel,\n sequence: this.memoryCache.lastKnownGood.sequence,\n stale: age > this.cacheTtl,\n fetchedAt: this.memoryCache.lastKnownGood.fetchedAt,\n etag: this.memoryCache.lastKnownGood.etag,\n error: this.currentStatus?.error,\n };\n }\n\n /**\n * Save to persistent storage\n */\n private async saveToStorage(cached: CachedRegistry): Promise<void> {\n if (!this.storage) return;\n\n const key = `registry_${this.channel}`;\n const value = JSON.stringify(cached);\n await this.storage.set(key, value);\n }\n\n /**\n * Load from persistent storage\n */\n private async loadFromStorage(): Promise<void> {\n if (!this.storage) return;\n\n const key = `registry_${this.channel}`;\n const value = await this.storage.get(key);\n if (value) {\n try {\n const cached = JSON.parse(value) as CachedRegistry;\n this.memoryCache.lastKnownGood = cached;\n } catch {\n // Ignore parse errors\n }\n }\n }\n\n /**\n * Get all wallets\n */\n async getWallets(): Promise<WalletInfo[]> {\n const registry = await this.getRegistry();\n return registry.wallets.map((entry) =>\n registryEntryToWalletInfo(entry, registry.metadata.channel)\n );\n }\n\n /**\n * Get wallet by ID\n */\n async getWallet(walletId: string): Promise<WalletInfo> {\n const registry = await this.getRegistry();\n const entry = registry.wallets.find((w) => w.id === walletId);\n\n if (!entry) {\n throw new WalletNotFoundError(walletId);\n }\n\n return registryEntryToWalletInfo(entry, registry.metadata.channel);\n }\n\n /**\n * Get wallet entry (includes adapter config)\n */\n async getWalletEntry(walletId: string): Promise<RegistryWalletEntry> {\n const registry = await this.getRegistry();\n const entry = registry.wallets.find((w) => w.id === walletId);\n\n if (!entry) {\n throw new WalletNotFoundError(walletId);\n }\n\n if (!validateWalletEntry(entry)) {\n throw new RegistrySchemaInvalidError(\n `Invalid wallet entry for ${walletId}`,\n { url: this.getRegistryUrl() }\n );\n }\n\n return entry;\n }\n\n /**\n * Clear cache\n */\n clearCache(): void {\n this.memoryCache.lastKnownGood = null;\n this.memoryCache.lastAttempt = null;\n this.memoryCache.refreshPromise = null;\n this.currentStatus = null;\n\n if (this.storage) {\n this.storage.remove(`registry_${this.channel}`).catch(() => {\n // Ignore errors\n });\n }\n }\n\n /**\n * Check if cache is valid\n */\n isCacheValid(): boolean {\n if (!this.enableCache || !this.memoryCache.lastKnownGood) {\n return false;\n }\n\n const now = Date.now();\n return now - this.memoryCache.lastKnownGood.fetchedAt < this.cacheTtl;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/schema.ts","../src/client.ts"],"names":["toWalletId","signature","RegistryFetchFailedError","RegistrySchemaInvalidError","RegistryVerificationFailedError","WalletNotFoundError"],"mappings":";;;;;AAqBO,IAAM,uBAAA,GAA0B;AAyGhC,SAAS,iBACd,QAAA,EAC8B;AAC9B,EAAA,IAAI,OAAO,QAAA,KAAa,QAAA,IAAY,QAAA,KAAa,IAAA,EAAM;AACrD,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,MAAM,CAAA,GAAI,QAAA;AAGV,EAAA,IAAI,CAAC,CAAA,CAAE,QAAA,IAAY,OAAO,CAAA,CAAE,aAAa,QAAA,EAAU;AACjD,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,MAAM,WAAW,CAAA,CAAE,QAAA;AACnB,EAAA,IACE,OAAO,QAAA,CAAS,eAAA,KAAoB,QAAA,IACpC,OAAO,QAAA,CAAS,aAAA,KAAkB,QAAA,IAClC,OAAO,SAAS,WAAA,KAAgB,QAAA,IAChC,OAAO,QAAA,CAAS,YAAY,QAAA,IAC3B,QAAA,CAAS,OAAA,KAAY,QAAA,IAAY,QAAA,CAAS,OAAA,KAAY,MAAA,IACvD,OAAO,SAAS,QAAA,KAAa,QAAA,IAC7B,CAAC,MAAA,CAAO,UAAU,QAAA,CAAS,QAAQ,CAAA,IACnC,QAAA,CAAS,WAAW,CAAA,EACpB;AACA,IAAA,OAAO,KAAA;AAAA,EACT;AAGA,EAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,CAAA,CAAE,OAAO,CAAA,EAAG;AAC7B,IAAA,OAAO,KAAA;AAAA,EACT;AAGA,EAAA,MAAM,SAAA,uBAAgB,GAAA,EAAY;AAClC,EAAA,KAAA,MAAW,MAAA,IAAU,EAAE,OAAA,EAAS;AAC9B,IAAA,IAAI,CAAC,mBAAA,CAAoB,MAAM,CAAA,EAAG;AAChC,MAAA,OAAO,KAAA;AAAA,IACT;AAEA,IAAA,MAAM,KAAA,GAAQ,MAAA;AACd,IAAA,IAAI,SAAA,CAAU,GAAA,CAAI,KAAA,CAAM,EAAE,CAAA,EAAG;AAC3B,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,SAAA,CAAU,GAAA,CAAI,MAAM,EAAE,CAAA;AAAA,EACxB;AAEA,EAAA,OAAO,IAAA;AACT;AAKO,SAAS,oBACd,KAAA,EAC8B;AAC9B,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,KAAU,IAAA,EAAM;AAC/C,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,MAAM,CAAA,GAAI,KAAA;AAEV,EAAA,OACE,OAAO,CAAA,CAAE,EAAA,KAAO,QAAA,IAChB,OAAO,EAAE,IAAA,KAAS,QAAA,IAClB,KAAA,CAAM,OAAA,CAAQ,EAAE,iBAAiB,CAAA,IACjC,OAAO,CAAA,CAAE,YAAA,KAAiB,YAC1B,CAAA,CAAE,YAAA,KAAiB,IAAA,IACnB,OAAO,EAAE,OAAA,KAAY,QAAA,IACrB,CAAA,CAAE,OAAA,KAAY,QACd,OAAQ,CAAA,CAAE,OAAA,CAAoC,IAAA,KAAS,aACtD,CAAA,CAAE,eAAA,KAAoB,UAAa,KAAA,CAAM,OAAA,CAAQ,EAAE,eAAe,CAAA,CAAA;AAEvE;AAKO,SAAS,yBAAA,CACd,OACA,OAAA,EACY;AACZ,EAAA,MAAM,YAAA,GAAgC,CAAC,SAAA,EAAW,YAAY,CAAA;AAC9D,EAAA,IAAI,KAAA,CAAM,aAAa,WAAA,EAAa;AAClC,IAAA,YAAA,CAAa,KAAK,aAAa,CAAA;AAAA,EACjC;AACA,EAAA,IAAI,KAAA,CAAM,aAAa,eAAA,EAAiB;AACtC,IAAA,YAAA,CAAa,KAAK,iBAAiB,CAAA;AAAA,EACrC;AACA,EAAA,IAAI,KAAA,CAAM,aAAa,iBAAA,EAAmB;AACxC,IAAA,YAAA,CAAa,KAAK,mBAAmB,CAAA;AAAA,EACvC;AACA,EAAA,IAAI,KAAA,CAAM,aAAa,iBAAA,EAAmB;AACxC,IAAA,YAAA,CAAa,KAAK,QAAQ,CAAA;AAAA,EAC5B;AAEA,EAAA,OAAO;AAAA,IACL,QAAA,EAAUA,eAAA,CAAW,KAAA,CAAM,EAAE,CAAA;AAAA,IAC7B,MAAM,KAAA,CAAM,IAAA;AAAA,IACZ,OAAA,EAAS,MAAM,QAAA,IAAY,EAAA;AAAA,IAC3B,KAAA,EAAO;AAAA,MACL,IAAI,KAAA,CAAM,IAAA;AAAA,MACV,IAAI,KAAA,CAAM,IAAA;AAAA,MACV,IAAI,KAAA,CAAM;AAAA,KACZ;AAAA,IACA,QAAA,EAAU,SAAA;AAAA,IACV,YAAA;AAAA,IACA,YAAA,EAAc,MAAM,YAAA,GAChB;AAAA,MACE,WAAA,EAAa,MAAM,YAAA,CAAa,cAAA;AAAA,MAChC,WAAA,EAAa,MAAM,YAAA,CAAa,WAAA;AAAA,MAChC,cAAA,EAAgB,MAAM,YAAA,CAAa;AAAA,KACrC,GACA,MAAA;AAAA,IACJ,OAAA,EAAS;AAAA,MACP,WAAA,EAAa,MAAM,OAAA,CAAQ,IAAA;AAAA,MAC3B,YAAA,EAAc,MAAM,UAAA,IAAc;AAAA,KACpC;AAAA,IACA,MAAM,KAAA,CAAM,QAAA,GAAW,CAAC,KAAA,CAAM,QAAQ,IAAI,EAAC;AAAA,IAC3C,eAAe,KAAA,CAAM,UAAA;AAAA,IACrB,UAAU,KAAA,CAAM,iBAAA;AAAA,IAChB,OAAA;AAAA;AAAA,IAEA,GAAI,KAAA,CAAM,eAAA,GACN,EAAE,UAAU,EAAE,eAAA,EAAiB,IAAA,CAAK,SAAA,CAAU,KAAA,CAAM,eAAe,CAAA,EAAE,KACrE;AAAC,GACP;AACF;AAKO,SAAS,wBACd,KAAA,EACY;AACZ,EAAA,OAAO,yBAAA,CAA0B,OAAO,QAAQ,CAAA;AAClD;ACpMA,IAAM,oBAAA,GAAuB,iCAAA;AAKtB,IAAM,iBAAN,MAAqB;AAAA,EAClB,OAAA;AAAA,EACA,OAAA;AAAA,EACA,UAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,WAAA;AAAA,EACA,OAAA;AAAA,EACA,YAAA;AAAA,EACA,OAAA;AAAA;AAAA,EAGA,WAAA,GAIJ;AAAA,IACF,aAAA,EAAe,IAAA;AAAA,IACf,WAAA,EAAa,IAAA;AAAA,IACb,cAAA,EAAgB;AAAA,GAClB;AAAA;AAAA,EAGQ,aAAA,GAAuC,IAAA;AAAA,EAE/C,WAAA,CAAY,OAAA,GAAiC,EAAC,EAAG;AAC/C,IAAA,IAAA,CAAK,OAAA,GAAU,QAAQ,WAAA,IAAe,oBAAA;AACtC,IAAA,IAAA,CAAK,OAAA,GAAU,QAAQ,OAAA,IAAW,QAAA;AAClC,IAAA,IAAA,CAAK,UAAA,GAAa,OAAA,CAAQ,kBAAA,IAAsB,EAAC;AACjD,IAAA,IAAA,CAAK,QAAA,GAAW,OAAA,CAAQ,QAAA,IAAY,EAAA,GAAK,EAAA,GAAK,GAAA;AAC9C,IAAA,IAAA,CAAK,QAAA,GAAW,OAAA,CAAQ,QAAA,IAAY,EAAA,GAAK,KAAK,EAAA,GAAK,GAAA;AACnD,IAAA,IAAA,CAAK,WAAA,GAAc,QAAQ,WAAA,KAAgB,KAAA;AAG3C,IAAA,IAAI,QAAQ,KAAA,EAAO;AACjB,MAAA,IAAA,CAAK,UAAU,OAAA,CAAQ,KAAA;AAAA,IACzB,CAAA,MAAA,IAAW,OAAO,MAAA,KAAW,WAAA,IAAe,OAAO,KAAA,EAAO;AACxD,MAAA,IAAA,CAAK,OAAA,GAAU,MAAA,CAAO,KAAA,CAAM,IAAA,CAAK,MAAM,CAAA;AAAA,IACzC,CAAA,MAAA,IAAW,OAAO,UAAA,KAAe,WAAA,IAAe,WAAW,KAAA,EAAO;AAChE,MAAA,IAAA,CAAK,OAAA,GAAU,UAAA,CAAW,KAAA,CAAM,IAAA,CAAK,UAAU,CAAA;AAAA,IACjD,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,OAAA,GAAU,KAAA;AAAA,IACjB;AACA,IAAA,IAAA,CAAK,YAAA,GAAe,QAAQ,YAAA,IAAgB,GAAA;AAC5C,IAAA,IAAA,CAAK,UAAU,OAAA,CAAQ,OAAA;AAGvB,IAAA,IAAI,KAAK,OAAA,EAAS;AAChB,MAAA,IAAA,CAAK,eAAA,EAAgB,CAAE,KAAA,CAAM,MAAM;AAAA,MAEnC,CAAC,CAAA;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,cAAA,GAAyB;AAC/B,IAAA,OAAO,CAAA,EAAG,IAAA,CAAK,OAAO,CAAA,IAAA,EAAO,KAAK,OAAO,CAAA,cAAA,CAAA;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAA,GAA0B;AAChC,IAAA,OAAO,CAAA,EAAG,IAAA,CAAK,OAAO,CAAA,IAAA,EAAO,KAAK,OAAO,CAAA,aAAA,CAAA;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,gBAAgB,SAAA,EAAuC;AACnE,IAAA,MAAM,SAAA,GAAY,MAAA,CAAO,IAAA,CAAK,SAAA,EAAW,QAAQ,CAAA;AACjD,IAAA,OAAO,MAAM,OAAO,MAAA,CAAO,SAAA;AAAA,MACzB,KAAA;AAAA,MACA,SAAA;AAAA,MACA;AAAA,QACE,IAAA,EAAM,SAAA;AAAA,QACN,UAAA,EAAY;AAAA,OACd;AAAA,MACA,IAAA;AAAA,MACA,CAAC,QAAQ;AAAA,KACX;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,eAAA,CACZ,YAAA,EACA,SAAA,EACA,SAAA,EACkB;AAClB,IAAA,IAAI,SAAA,CAAU,cAAc,SAAA,EAAW;AACrC,MAAA,OAAO,KAAA;AAAA,IACT;AAEA,IAAA,MAAM,IAAA,GAAO,IAAI,WAAA,EAAY,CAAE,OAAO,YAAY,CAAA;AAClD,IAAA,MAAM,SAAA,GAAY,MAAA,CAAO,IAAA,CAAK,SAAA,CAAU,WAAW,QAAQ,CAAA;AAC3D,IAAA,OAAO,MAAM,MAAA,CAAO,MAAA,CAAO,OAAO,SAAA,EAAW,SAAA,EAAW,WAAW,IAAI,CAAA;AAAA,EACzE;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,uBAAA,CACZ,YAAA,EACA,SAAA,EACkB;AAClB,IAAA,IAAI,IAAA,CAAK,UAAA,CAAW,MAAA,KAAW,CAAA,EAAG;AAEhC,MAAA,OAAO,IAAA;AAAA,IACT;AAGA,IAAA,KAAA,MAAW,YAAA,IAAgB,KAAK,UAAA,EAAY;AAC1C,MAAA,IAAI;AACF,QAAA,MAAM,SAAA,GAAY,MAAM,IAAA,CAAK,eAAA,CAAgB,YAAY,CAAA;AACzD,QAAA,MAAM,UAAU,MAAM,IAAA,CAAK,eAAA,CAAgB,YAAA,EAAc,WAAW,SAAS,CAAA;AAC7E,QAAA,IAAI,OAAA,EAAS;AACX,UAAA,OAAO,IAAA;AAAA,QACT;AAAA,MACF,CAAA,CAAA,MAAQ;AAEN,QAAA;AAAA,MACF;AAAA,IACF;AAEA,IAAA,OAAO,KAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,gBAAA,GAIX;AACD,IAAA,MAAM,WAAA,GAAc,KAAK,cAAA,EAAe;AACxC,IAAA,MAAM,MAAA,GAAS,KAAK,eAAA,EAAgB;AACpC,IAAA,MAAM,gBAAA,GAAmB,IAAA,CAAK,UAAA,CAAW,MAAA,GAAS,CAAA;AAGlD,IAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,IAAA,MAAM,YAAY,UAAA,CAAW,MAAM,WAAW,KAAA,EAAM,EAAG,KAAK,YAAY,CAAA;AAExE,IAAA,IAAI;AAEJ,MAAA,MAAM,gBAAA,GAAmB,MAAM,IAAA,CAAK,OAAA,CAAQ,WAAA,EAAa;AAAA,QACvD,OAAA,EAAS;AAAA,UACP,QAAA,EAAU,kBAAA;AAAA,UACV,eAAA,EAAiB,IAAA,CAAK,WAAA,CAAY,aAAA,EAAe,IAAA,IAAQ;AAAA,SAC3D;AAAA,QACA,QAAQ,UAAA,CAAW;AAAA,OACpB,CAAA;AAGD,MAAA,IAAI,gBAAA,CAAiB,WAAW,GAAA,EAAK;AACnC,QAAA,IAAI,IAAA,CAAK,YAAY,aAAA,EAAe;AAGlC,UAAA,IAAIC,UAAAA;AACJ,UAAA,IAAI,gBAAA,EAAkB;AAEpB,YAAA,IAAI;AACF,cAAA,MAAM,WAAA,GAAc,MAAM,IAAA,CAAK,OAAA,CAAQ,MAAA,EAAQ;AAAA,gBAC7C,OAAA,EAAS,EAAE,QAAA,EAAU,kBAAA,EAAmB;AAAA,gBACxC,QAAQ,UAAA,CAAW;AAAA,eACpB,CAAA;AACD,cAAA,IAAI,YAAY,EAAA,EAAI;AAClB,gBAAAA,aAAY,IAAA,CAAK,KAAA,CAAM,MAAM,WAAA,CAAY,MAAM,CAAA;AAAA,cACjD,CAAA,MAAO;AAEL,gBAAAA,UAAAA,GAAY,EAAE,SAAA,EAAW,SAAA,EAAW,SAAA,EAAW,EAAA,EAAI,cAAA,EAAgB,EAAA,EAAI,QAAA,EAAA,iBAAU,IAAI,IAAA,EAAK,EAAE,aAAY,EAAE;AAAA,cAC5G;AAAA,YACF,CAAA,CAAA,MAAQ;AACN,cAAAA,UAAAA,GAAY,EAAE,SAAA,EAAW,SAAA,EAAW,SAAA,EAAW,EAAA,EAAI,cAAA,EAAgB,EAAA,EAAI,QAAA,EAAA,iBAAU,IAAI,IAAA,EAAK,EAAE,aAAY,EAAE;AAAA,YAC5G;AAAA,UACF,CAAA,MAAO;AAEL,YAAAA,UAAAA,GAAY,EAAE,SAAA,EAAW,SAAA,EAAW,SAAA,EAAW,EAAA,EAAI,cAAA,EAAgB,EAAA,EAAI,QAAA,EAAA,iBAAU,IAAI,IAAA,EAAK,EAAE,aAAY,EAAE;AAAA,UAC5G;AAEA,UAAA,OAAO;AAAA,YACL,QAAA,EAAU,IAAA,CAAK,WAAA,CAAY,aAAA,CAAc,QAAA;AAAA,YACzC,SAAA,EAAAA,UAAAA;AAAA,YACA,IAAA,EAAM,IAAA,CAAK,WAAA,CAAY,aAAA,CAAc;AAAA,WACvC;AAAA,QACF;AAAA,MACF;AAEA,MAAA,IAAI,CAAC,iBAAiB,EAAA,EAAI;AACxB,QAAA,MAAM,IAAIC,6BAAA;AAAA,UACR,WAAA;AAAA,UACA,IAAI,MAAM,CAAA,EAAG,gBAAA,CAAiB,MAAM,CAAA,CAAA,EAAI,gBAAA,CAAiB,UAAU,CAAA,CAAE;AAAA,SACvE;AAAA,MACF;AAEA,MAAA,MAAM,YAAA,GAAe,MAAM,gBAAA,CAAiB,IAAA,EAAK;AACjD,MAAA,MAAM,QAAA,GAAW,IAAA,CAAK,KAAA,CAAM,YAAY,CAAA;AACxC,MAAA,MAAM,IAAA,GAAO,gBAAA,CAAiB,OAAA,CAAQ,GAAA,CAAI,MAAM,CAAA,IAAK,KAAA,CAAA;AAGrD,MAAA,IAAI,CAAC,gBAAA,CAAiB,QAAQ,CAAA,EAAG;AAC/B,QAAA,MAAM,IAAIC,+BAAA;AAAA,UACR,yBAAA;AAAA,UACA,EAAE,KAAK,WAAA;AAAY,SACrB;AAAA,MACF;AAGA,MAAA,IAAI,SAAA;AAEJ,MAAA,IAAI,gBAAA,EAAkB;AAEpB,QAAA,MAAM,WAAA,GAAc,MAAM,IAAA,CAAK,OAAA,CAAQ,MAAA,EAAQ;AAAA,UAC7C,OAAA,EAAS;AAAA,YACP,QAAA,EAAU;AAAA,WACZ;AAAA,UACA,QAAQ,UAAA,CAAW;AAAA,SACpB,CAAA;AAED,QAAA,IAAI,CAAC,YAAY,EAAA,EAAI;AACnB,UAAA,MAAM,IAAID,6BAAA;AAAA,YACR,MAAA;AAAA,YACA,IAAI,MAAM,CAAA,EAAG,WAAA,CAAY,MAAM,CAAA,CAAA,EAAI,WAAA,CAAY,UAAU,CAAA,CAAE;AAAA,WAC7D;AAAA,QACF;AACA,QAAA,SAAA,GAAY,IAAA,CAAK,KAAA,CAAM,MAAM,WAAA,CAAY,MAAM,CAAA;AAG/C,QAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,uBAAA,CAAwB,cAAc,SAAS,CAAA;AAC3E,QAAA,IAAI,CAAC,QAAA,EAAU;AACb,UAAA,MAAM,IAAIE,oCAAA;AAAA,YACR,+BAAA;AAAA,YACA,EAAE,KAAK,WAAA;AAAY,WACrB;AAAA,QACF;AAAA,MACF,CAAA,MAAO;AAEL,QAAA,OAAA,CAAQ,IAAI,iFAAiF,CAAA;AAC7F,QAAA,SAAA,GAAY,EAAE,SAAA,EAAW,SAAA,EAAW,SAAA,EAAW,EAAA,EAAI,cAAA,EAAgB,EAAA,EAAI,QAAA,EAAA,iBAAU,IAAI,IAAA,EAAK,EAAE,WAAA,EAAY,EAAE;AAAA,MAC5G;AAGA,MAAA,IAAI,IAAA,CAAK,YAAY,aAAA,EAAe;AAClC,QAAA,IAAI,SAAS,QAAA,CAAS,QAAA,GAAW,IAAA,CAAK,WAAA,CAAY,cAAc,QAAA,EAAU;AACxE,UAAA,MAAM,IAAIA,oCAAA;AAAA,YACR,CAAA,6BAAA,EAAgC,SAAS,QAAA,CAAS,QAAQ,MAAM,IAAA,CAAK,WAAA,CAAY,cAAc,QAAQ,CAAA,CAAA;AAAA,YACvG,EAAE,KAAK,WAAA;AAAY,WACrB;AAAA,QACF;AAAA,MACF;AAEA,MAAA,OAAO,EAAE,QAAA,EAAU,SAAA,EAAW,IAAA,EAAK;AAAA,IACnC,CAAA,SAAE;AACA,MAAA,YAAA,CAAa,SAAS,CAAA;AAAA,IACxB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,WAAA,GAAyC;AAE7C,IAAA,IAAI,IAAA,CAAK,YAAY,aAAA,EAAe;AAClC,MAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,MAAA,MAAM,GAAA,GAAM,GAAA,GAAM,IAAA,CAAK,WAAA,CAAY,aAAA,CAAc,SAAA;AAGjD,MAAA,IAAI,GAAA,GAAM,KAAK,QAAA,EAAU;AAEvB,QAAA,IAAI,CAAC,IAAA,CAAK,WAAA,CAAY,cAAA,EAAgB;AACpC,UAAA,IAAA,CAAK,WAAA,CAAY,cAAA,GAAiB,IAAA,CAAK,eAAA,EAAgB;AAAA,QACzD;AACA,QAAA,OAAO,IAAA,CAAK,YAAY,aAAA,CAAc,QAAA;AAAA,MACxC;AAGA,MAAA,IAAI,GAAA,GAAM,KAAK,QAAA,EAAU;AAEvB,QAAA,IAAI,CAAC,IAAA,CAAK,WAAA,CAAY,cAAA,EAAgB;AACpC,UAAA,IAAA,CAAK,WAAA,CAAY,cAAA,GAAiB,IAAA,CAAK,eAAA,EAAgB;AAAA,QACzD;AACA,QAAA,OAAO,IAAA,CAAK,YAAY,aAAA,CAAc,QAAA;AAAA,MACxC;AAAA,IACF;AAGA,IAAA,OAAO,MAAM,KAAK,eAAA,EAAgB;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,eAAA,GAA6C;AAEzD,IAAA,IAAI,IAAA,CAAK,YAAY,cAAA,EAAgB;AACnC,MAAA,OAAO,MAAM,KAAK,WAAA,CAAY,cAAA;AAAA,IAChC;AAEA,IAAA,MAAM,kBAAkB,YAAY;AAClC,MAAA,IAAI;AACF,QAAA,MAAM,EAAE,QAAA,EAAU,IAAA,EAAK,GAAI,MAAM,KAAK,gBAAA,EAAiB;AAEvD,QAAA,OAAA,CAAQ,IAAI,iDAAA,EAAmD;AAAA,UAC7D,OAAA,EAAS,SAAS,QAAA,CAAS,OAAA;AAAA,UAC3B,QAAA,EAAU,SAAS,QAAA,CAAS,QAAA;AAAA,UAC5B,WAAA,EAAa,SAAS,OAAA,CAAQ;AAAA,SAC/B,CAAA;AAGD,QAAA,MAAM,MAAA,GAAyB;AAAA,UAC7B,QAAA;AAAA,UACA,QAAA,EAAU,IAAA;AAAA,UACV,SAAA,EAAW,KAAK,GAAA,EAAI;AAAA,UACpB,IAAA;AAAA,UACA,QAAA,EAAU,SAAS,QAAA,CAAS;AAAA,SAC9B;AAEA,QAAA,IAAA,CAAK,YAAY,aAAA,GAAgB,MAAA;AACjC,QAAA,IAAA,CAAK,YAAY,WAAA,GAAc;AAAA,UAC7B,SAAA,EAAW,KAAK,GAAA;AAAI,SACtB;AAGA,QAAA,IAAA,CAAK,YAAA,CAAa;AAAA,UAChB,MAAA,EAAQ,SAAA;AAAA,UACR,QAAA,EAAU,IAAA;AAAA,UACV,OAAA,EAAS,SAAS,QAAA,CAAS,OAAA;AAAA,UAC3B,QAAA,EAAU,SAAS,QAAA,CAAS,QAAA;AAAA,UAC5B,KAAA,EAAO,KAAA;AAAA,UACP,WAAW,MAAA,CAAO,SAAA;AAAA,UAClB;AAAA,SACD,CAAA;AAGD,QAAA,IAAI,KAAK,OAAA,EAAS;AAChB,UAAA,MAAM,IAAA,CAAK,cAAc,MAAM,CAAA;AAAA,QACjC;AAEA,QAAA,OAAO,QAAA;AAAA,MACT,SAAS,KAAA,EAAO;AAEd,QAAA,IAAA,CAAK,YAAY,WAAA,GAAc;AAAA,UAC7B,SAAA,EAAW,KAAK,GAAA,EAAI;AAAA,UACpB,SAAA,EACE,iBAAiBF,6BAAA,GACb,uBAAA,GACA,iBAAiBE,oCAAA,GACf,8BAAA,GACA,KAAA,YAAiBD,+BAAA,GACf,yBAAA,GACA;AAAA,SACZ;AAGA,QAAA,MAAM,aAAA,GAAgB,KAAK,WAAA,CAAY,aAAA;AACvC,QAAA,IAAI,aAAA,EAAe;AACjB,UAAA,MAAM,cAAc,KAAA,YAAiBD,6BAAA,IACnC,iBAAiBE,oCAAA,IACjB,KAAA,YAAiBD,kCACf,KAAA,GACA,MAAA;AACJ,UAAA,IAAA,CAAK,YAAA,CAAa;AAAA,YAChB,MAAA,EAAQ,OAAA;AAAA,YACR,UAAU,aAAA,CAAc,QAAA;AAAA,YACxB,OAAA,EAAS,aAAA,CAAc,QAAA,CAAS,QAAA,CAAS,OAAA;AAAA,YACzC,UAAU,aAAA,CAAc,QAAA;AAAA,YACxB,OAAO,IAAA,CAAK,GAAA,EAAI,GAAI,aAAA,CAAc,YAAY,IAAA,CAAK,QAAA;AAAA,YACnD,WAAW,aAAA,CAAc,SAAA;AAAA,YACzB,MAAM,aAAA,CAAc,IAAA;AAAA,YACpB,KAAA,EAAO;AAAA,WACR,CAAA;AAGD,UAAA,OAAO,aAAA,CAAc,QAAA;AAAA,QACvB;AAGA,QAAA,MAAM,KAAA;AAAA,MACR,CAAA,SAAE;AACA,QAAA,IAAA,CAAK,YAAY,cAAA,GAAiB,IAAA;AAAA,MACpC;AAAA,IACF,CAAA,GAAG;AAEH,IAAA,IAAA,CAAK,YAAY,cAAA,GAAiB,cAAA;AAClC,IAAA,OAAO,MAAM,cAAA;AAAA,EACf;AAAA;AAAA;AAAA;AAAA,EAKQ,aAAa,MAAA,EAA8B;AACjD,IAAA,IAAA,CAAK,aAAA,GAAgB,MAAA;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,SAAA,GAAmC;AACjC,IAAA,IAAI,CAAC,IAAA,CAAK,WAAA,CAAY,aAAA,EAAe;AACnC,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,IAAA,MAAM,GAAA,GAAM,GAAA,GAAM,IAAA,CAAK,WAAA,CAAY,aAAA,CAAc,SAAA;AAEjD,IAAA,OAAO;AAAA,MACL,MAAA,EAAQ,IAAA,CAAK,aAAA,EAAe,MAAA,IAAU,OAAA;AAAA,MACtC,QAAA,EAAU,IAAA,CAAK,WAAA,CAAY,aAAA,CAAc,QAAA;AAAA,MACzC,OAAA,EAAS,IAAA,CAAK,WAAA,CAAY,aAAA,CAAc,SAAS,QAAA,CAAS,OAAA;AAAA,MAC1D,QAAA,EAAU,IAAA,CAAK,WAAA,CAAY,aAAA,CAAc,QAAA;AAAA,MACzC,KAAA,EAAO,MAAM,IAAA,CAAK,QAAA;AAAA,MAClB,SAAA,EAAW,IAAA,CAAK,WAAA,CAAY,aAAA,CAAc,SAAA;AAAA,MAC1C,IAAA,EAAM,IAAA,CAAK,WAAA,CAAY,aAAA,CAAc,IAAA;AAAA,MACrC,KAAA,EAAO,KAAK,aAAA,EAAe;AAAA,KAC7B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,cAAc,MAAA,EAAuC;AACjE,IAAA,IAAI,CAAC,KAAK,OAAA,EAAS;AAEnB,IAAA,MAAM,GAAA,GAAM,CAAA,SAAA,EAAY,IAAA,CAAK,OAAO,CAAA,CAAA;AACpC,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,SAAA,CAAU,MAAM,CAAA;AACnC,IAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,GAAA,EAAK,KAAK,CAAA;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,eAAA,GAAiC;AAC7C,IAAA,IAAI,CAAC,KAAK,OAAA,EAAS;AAEnB,IAAA,MAAM,GAAA,GAAM,CAAA,SAAA,EAAY,IAAA,CAAK,OAAO,CAAA,CAAA;AACpC,IAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,OAAA,CAAQ,IAAI,GAAG,CAAA;AACxC,IAAA,IAAI,KAAA,EAAO;AACT,MAAA,IAAI;AACF,QAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,KAAK,CAAA;AAC/B,QAAA,IAAA,CAAK,YAAY,aAAA,GAAgB,MAAA;AAAA,MACnC,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,UAAA,GAAoC;AACxC,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,WAAA,EAAY;AACxC,IAAA,OAAO,SAAS,OAAA,CAAQ,GAAA;AAAA,MAAI,CAAC,KAAA,KAC3B,yBAAA,CAA0B,KAAA,EAAO,QAAA,CAAS,SAAS,OAAO;AAAA,KAC5D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,UAAU,QAAA,EAAuC;AACrD,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,WAAA,EAAY;AACxC,IAAA,MAAM,KAAA,GAAQ,SAAS,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,OAAO,QAAQ,CAAA;AAE5D,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,MAAM,IAAIE,yBAAoB,QAAQ,CAAA;AAAA,IACxC;AAEA,IAAA,OAAO,yBAAA,CAA0B,KAAA,EAAO,QAAA,CAAS,QAAA,CAAS,OAAO,CAAA;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eAAe,QAAA,EAAgD;AACnE,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,WAAA,EAAY;AACxC,IAAA,MAAM,KAAA,GAAQ,SAAS,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,OAAO,QAAQ,CAAA;AAE5D,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,MAAM,IAAIA,yBAAoB,QAAQ,CAAA;AAAA,IACxC;AAEA,IAAA,IAAI,CAAC,mBAAA,CAAoB,KAAK,CAAA,EAAG;AAC/B,MAAA,MAAM,IAAIF,+BAAA;AAAA,QACR,4BAA4B,QAAQ,CAAA,CAAA;AAAA,QACpC,EAAE,GAAA,EAAK,IAAA,CAAK,cAAA,EAAe;AAAE,OAC/B;AAAA,IACF;AAEA,IAAA,OAAO,KAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,UAAA,GAAmB;AACjB,IAAA,IAAA,CAAK,YAAY,aAAA,GAAgB,IAAA;AACjC,IAAA,IAAA,CAAK,YAAY,WAAA,GAAc,IAAA;AAC/B,IAAA,IAAA,CAAK,YAAY,cAAA,GAAiB,IAAA;AAClC,IAAA,IAAA,CAAK,aAAA,GAAgB,IAAA;AAErB,IAAA,IAAI,KAAK,OAAA,EAAS;AAChB,MAAA,IAAA,CAAK,OAAA,CAAQ,OAAO,CAAA,SAAA,EAAY,IAAA,CAAK,OAAO,CAAA,CAAE,CAAA,CAAE,MAAM,MAAM;AAAA,MAE5D,CAAC,CAAA;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,YAAA,GAAwB;AACtB,IAAA,IAAI,CAAC,IAAA,CAAK,WAAA,IAAe,CAAC,IAAA,CAAK,YAAY,aAAA,EAAe;AACxD,MAAA,OAAO,KAAA;AAAA,IACT;AAEA,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,IAAA,OAAO,GAAA,GAAM,IAAA,CAAK,WAAA,CAAY,aAAA,CAAc,YAAY,IAAA,CAAK,QAAA;AAAA,EAC/D;AACF","file":"index.js","sourcesContent":["/**\n * Wallet Registry Schema v1\n * \n * This schema defines the structure of the wallet registry JSON.\n * The registry is versioned and supports:\n * - Multiple wallet entries\n * - Versioning and rollback\n * - Integrity checks (Ed25519 signatures)\n * - Multi-channel (stable/beta)\n * - Forward compatibility\n * \n * References:\n * - Wallet Integration Guide: https://docs.digitalasset.com/integrate/devnet/index.html\n */\n\nimport type { WalletInfo, NetworkId, CapabilityKey } from '@partylayer/core';\nimport { toWalletId } from '@partylayer/core';\n\n/**\n * Registry schema version\n */\nexport const REGISTRY_SCHEMA_VERSION = '1.0.0';\n\n/**\n * Registry channel\n */\nexport type RegistryChannel = 'stable' | 'beta';\n\n/**\n * Wallet entry in registry\n */\nexport interface RegistryWalletEntry {\n /** Wallet identifier (must be unique within channel) */\n id: string;\n /** Display name */\n name: string;\n /** Short description */\n description?: string;\n /** Homepage URL */\n homepage?: string;\n /** Icon URL (should be absolute) */\n icon?: string;\n /** Supported networks */\n supportedNetworks: NetworkId[];\n /** Wallet capabilities */\n capabilities: {\n signMessage: boolean;\n signTransaction: boolean;\n submitTransaction: boolean;\n transactionStatus: boolean;\n switchNetwork: boolean;\n multiParty: boolean;\n };\n /** Adapter configuration */\n adapter: {\n /** Adapter type/name */\n type: string;\n /** Adapter-specific configuration */\n config?: Record<string, unknown>;\n };\n /** Installation detection hints */\n installation?: {\n /** Check if wallet is installed via window property */\n windowProperty?: string;\n /** Check if wallet is installed via script tag */\n scriptTag?: string;\n /** Check if wallet is installed via browser extension */\n extensionId?: string;\n };\n /** SDK version compatibility */\n sdkVersion?: string;\n /** Metadata version (for cache invalidation) */\n version?: string;\n /** Origin allowlist (optional - if present, only these origins can connect) */\n originAllowlist?: string[];\n}\n\n/**\n * Registry metadata\n */\nexport interface RegistryMetadata {\n /** Registry version (semver) */\n registryVersion: string;\n /** Schema version */\n schemaVersion: string;\n /** ISO 8601 timestamp when registry was published */\n publishedAt: string;\n /** Channel (stable or beta) */\n channel: RegistryChannel;\n /** Monotonic sequence number (increments on each update) */\n sequence: number;\n /** Registry publisher */\n publisher?: string;\n}\n\n/**\n * Wallet Registry v1 structure\n * \n * Note: Signature is NOT embedded. It's in a separate .sig file.\n */\nexport interface WalletRegistryV1 {\n /** Registry metadata */\n metadata: RegistryMetadata;\n /** Array of wallet entries */\n wallets: RegistryWalletEntry[];\n}\n\n/**\n * Registry signature file format\n * \n * This is stored separately as registry.sig\n */\nexport interface RegistrySignature {\n /** Signature algorithm (always 'ed25519') */\n algorithm: 'ed25519';\n /** Signature value (base64-encoded) */\n signature: string;\n /** Public key fingerprint (for key identification) */\n keyFingerprint: string;\n /** Timestamp when signed */\n signedAt: string;\n}\n\n/**\n * Validate registry structure\n */\nexport function validateRegistry(\n registry: unknown\n): registry is WalletRegistryV1 {\n if (typeof registry !== 'object' || registry === null) {\n return false;\n }\n\n const r = registry as Record<string, unknown>;\n\n // Check metadata\n if (!r.metadata || typeof r.metadata !== 'object') {\n return false;\n }\n\n const metadata = r.metadata as Record<string, unknown>;\n if (\n typeof metadata.registryVersion !== 'string' ||\n typeof metadata.schemaVersion !== 'string' ||\n typeof metadata.publishedAt !== 'string' ||\n typeof metadata.channel !== 'string' ||\n (metadata.channel !== 'stable' && metadata.channel !== 'beta') ||\n typeof metadata.sequence !== 'number' ||\n !Number.isInteger(metadata.sequence) ||\n metadata.sequence < 0\n ) {\n return false;\n }\n\n // Check wallets array\n if (!Array.isArray(r.wallets)) {\n return false;\n }\n\n // Validate each wallet entry\n const walletIds = new Set<string>();\n for (const wallet of r.wallets) {\n if (!validateWalletEntry(wallet)) {\n return false;\n }\n // Check uniqueness\n const entry = wallet as RegistryWalletEntry;\n if (walletIds.has(entry.id)) {\n return false;\n }\n walletIds.add(entry.id);\n }\n\n return true;\n}\n\n/**\n * Validate wallet entry\n */\nexport function validateWalletEntry(\n entry: unknown\n): entry is RegistryWalletEntry {\n if (typeof entry !== 'object' || entry === null) {\n return false;\n }\n\n const e = entry as Record<string, unknown>;\n\n return (\n typeof e.id === 'string' &&\n typeof e.name === 'string' &&\n Array.isArray(e.supportedNetworks) &&\n typeof e.capabilities === 'object' &&\n e.capabilities !== null &&\n typeof e.adapter === 'object' &&\n e.adapter !== null &&\n typeof (e.adapter as Record<string, unknown>).type === 'string' &&\n (e.originAllowlist === undefined || Array.isArray(e.originAllowlist))\n );\n}\n\n/**\n * Convert registry entry to wallet info\n */\nexport function registryEntryToWalletInfo(\n entry: RegistryWalletEntry,\n channel: RegistryChannel\n): WalletInfo {\n const capabilities: CapabilityKey[] = ['connect', 'disconnect'];\n if (entry.capabilities.signMessage) {\n capabilities.push('signMessage');\n }\n if (entry.capabilities.signTransaction) {\n capabilities.push('signTransaction');\n }\n if (entry.capabilities.submitTransaction) {\n capabilities.push('submitTransaction');\n }\n if (entry.capabilities.transactionStatus) {\n capabilities.push('events');\n }\n\n return {\n walletId: toWalletId(entry.id),\n name: entry.name,\n website: entry.homepage || '',\n icons: {\n sm: entry.icon,\n md: entry.icon,\n lg: entry.icon,\n },\n category: 'browser',\n capabilities,\n installHints: entry.installation\n ? {\n injectedKey: entry.installation.windowProperty,\n extensionId: entry.installation.extensionId,\n deepLinkScheme: entry.installation.scriptTag,\n }\n : undefined,\n adapter: {\n packageName: entry.adapter.type,\n versionRange: entry.sdkVersion || '*',\n },\n docs: entry.homepage ? [entry.homepage] : [],\n minSdkVersion: entry.sdkVersion,\n networks: entry.supportedNetworks,\n channel,\n // Store origin allowlist in metadata for SDK enforcement\n ...(entry.originAllowlist\n ? { metadata: { originAllowlist: JSON.stringify(entry.originAllowlist) } }\n : {}),\n };\n}\n\n/**\n * @deprecated Use registryEntryToWalletInfo instead\n */\nexport function registryEntryToMetadata(\n entry: RegistryWalletEntry\n): WalletInfo {\n return registryEntryToWalletInfo(entry, 'stable');\n}\n","/**\n * Registry client for fetching and caching wallet registry\n * \n * Features:\n * - Ed25519 signature verification\n * - Multi-channel support (stable/beta)\n * - Sequence number validation (prevents downgrades)\n * - Last-known-good caching\n * - SWR pattern (serve cached immediately, refresh in background)\n * - ETag support for efficient updates\n * \n * References:\n * - Wallet Integration Guide: https://docs.digitalasset.com/integrate/devnet/index.html\n */\n\nimport type { WalletInfo } from '@partylayer/core';\nimport {\n RegistryFetchFailedError,\n RegistryVerificationFailedError,\n RegistrySchemaInvalidError,\n WalletNotFoundError,\n} from '@partylayer/core';\nimport type {\n WalletRegistryV1,\n RegistryWalletEntry,\n RegistryChannel,\n RegistrySignature,\n} from './schema';\nimport {\n validateRegistry,\n validateWalletEntry,\n registryEntryToWalletInfo,\n} from './schema';\nimport type { RegistryStatus, CachedRegistry, LastFetchAttempt } from './status';\n\n/**\n * Registry client options\n */\nexport interface RegistryClientOptions {\n /** Base registry URL (client appends /v1/{channel}/registry.json) */\n registryUrl?: string;\n /** Registry channel */\n channel?: RegistryChannel;\n /** Public keys for signature verification (base64) */\n registryPublicKeys?: string[];\n /** Cache TTL in milliseconds (default: 1 hour) */\n cacheTtl?: number;\n /** Stale TTL in milliseconds (default: 24 hours - cache usable but marked stale) */\n staleTtl?: number;\n /** Enable cache (default: true) */\n enableCache?: boolean;\n /** Custom fetch function */\n fetch?: typeof fetch;\n /** Fetch timeout in milliseconds (default: 8000) */\n fetchTimeout?: number;\n /** Storage adapter for persistent cache */\n storage?: {\n get(key: string): Promise<string | null>;\n set(key: string, value: string): Promise<void>;\n remove(key: string): Promise<void>;\n };\n}\n\n/**\n * Default registry URL\n */\nconst DEFAULT_REGISTRY_URL = 'https://registry.partylayer.xyz';\n\n/**\n * Registry client\n */\nexport class RegistryClient {\n private baseUrl: string;\n private channel: RegistryChannel;\n private publicKeys: string[];\n private cacheTtl: number;\n private staleTtl: number;\n private enableCache: boolean;\n private fetchFn: typeof fetch;\n private fetchTimeout: number;\n private storage?: RegistryClientOptions['storage'];\n\n // In-memory cache\n private memoryCache: {\n lastKnownGood: CachedRegistry | null;\n lastAttempt: LastFetchAttempt | null;\n refreshPromise: Promise<WalletRegistryV1> | null;\n } = {\n lastKnownGood: null,\n lastAttempt: null,\n refreshPromise: null,\n };\n\n // Status tracking\n private currentStatus: RegistryStatus | null = null;\n\n constructor(options: RegistryClientOptions = {}) {\n this.baseUrl = options.registryUrl || DEFAULT_REGISTRY_URL;\n this.channel = options.channel || 'stable';\n this.publicKeys = options.registryPublicKeys || [];\n this.cacheTtl = options.cacheTtl || 60 * 60 * 1000; // 1 hour\n this.staleTtl = options.staleTtl || 24 * 60 * 60 * 1000; // 24 hours\n this.enableCache = options.enableCache !== false;\n // Bind fetch to prevent \"Illegal invocation\" error\n // Use global fetch directly to avoid context issues\n if (options.fetch) {\n this.fetchFn = options.fetch;\n } else if (typeof window !== 'undefined' && window.fetch) {\n this.fetchFn = window.fetch.bind(window);\n } else if (typeof globalThis !== 'undefined' && globalThis.fetch) {\n this.fetchFn = globalThis.fetch.bind(globalThis);\n } else {\n this.fetchFn = fetch;\n }\n this.fetchTimeout = options.fetchTimeout || 8000;\n this.storage = options.storage;\n\n // Load from persistent storage if available\n if (this.storage) {\n this.loadFromStorage().catch(() => {\n // Ignore errors on load\n });\n }\n }\n\n /**\n * Get registry URL for channel\n */\n private getRegistryUrl(): string {\n return `${this.baseUrl}/v1/${this.channel}/registry.json`;\n }\n\n /**\n * Get signature URL for channel\n */\n private getSignatureUrl(): string {\n return `${this.baseUrl}/v1/${this.channel}/registry.sig`;\n }\n\n /**\n * Import public key from base64\n */\n private async importPublicKey(keyBase64: string): Promise<CryptoKey> {\n const keyBuffer = Buffer.from(keyBase64, 'base64');\n return await crypto.subtle.importKey(\n 'raw',\n keyBuffer,\n {\n name: 'Ed25519',\n namedCurve: 'Ed25519',\n },\n true,\n ['verify']\n );\n }\n\n /**\n * Verify signature\n */\n private async verifySignature(\n registryJson: string,\n signature: RegistrySignature,\n publicKey: CryptoKey\n ): Promise<boolean> {\n if (signature.algorithm !== 'ed25519') {\n return false;\n }\n\n const data = new TextEncoder().encode(registryJson);\n const sigBuffer = Buffer.from(signature.signature, 'base64');\n return await crypto.subtle.verify('Ed25519', publicKey, sigBuffer, data);\n }\n\n /**\n * Verify registry signature\n */\n private async verifyRegistrySignature(\n registryJson: string,\n signature: RegistrySignature\n ): Promise<boolean> {\n if (this.publicKeys.length === 0) {\n // No public keys configured - skip verification (dev mode)\n return true;\n }\n\n // Try each public key\n for (const pubkeyBase64 of this.publicKeys) {\n try {\n const publicKey = await this.importPublicKey(pubkeyBase64);\n const isValid = await this.verifySignature(registryJson, signature, publicKey);\n if (isValid) {\n return true;\n }\n } catch {\n // Try next key\n continue;\n }\n }\n\n return false;\n }\n\n /**\n * Fetch registry and signature from network\n */\n private async fetchFromNetwork(): Promise<{\n registry: WalletRegistryV1;\n signature: RegistrySignature;\n etag?: string;\n }> {\n const registryUrl = this.getRegistryUrl();\n const sigUrl = this.getSignatureUrl();\n const requireSignature = this.publicKeys.length > 0;\n\n // AbortController for fetch timeout\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.fetchTimeout);\n\n try {\n // Fetch registry (always required)\n const registryResponse = await this.fetchFn(registryUrl, {\n headers: {\n 'Accept': 'application/json',\n 'If-None-Match': this.memoryCache.lastKnownGood?.etag || '',\n },\n signal: controller.signal,\n });\n\n // Handle 304 Not Modified\n if (registryResponse.status === 304) {\n if (this.memoryCache.lastKnownGood) {\n // For 304, we still need a signature object for return type\n // In dev mode, create dummy signature (skip fetch entirely)\n let signature: RegistrySignature;\n if (requireSignature) {\n // Production mode: try to fetch signature\n try {\n const sigResponse = await this.fetchFn(sigUrl, {\n headers: { 'Accept': 'application/json' },\n signal: controller.signal,\n });\n if (sigResponse.ok) {\n signature = JSON.parse(await sigResponse.text()) as RegistrySignature;\n } else {\n // Signature missing but we have cache - use dummy\n signature = { algorithm: 'ed25519', signature: '', keyFingerprint: '', signedAt: new Date().toISOString() };\n }\n } catch {\n signature = { algorithm: 'ed25519', signature: '', keyFingerprint: '', signedAt: new Date().toISOString() };\n }\n } else {\n // Dev mode: create dummy signature\n signature = { algorithm: 'ed25519', signature: '', keyFingerprint: '', signedAt: new Date().toISOString() };\n }\n \n return {\n registry: this.memoryCache.lastKnownGood.registry,\n signature,\n etag: this.memoryCache.lastKnownGood.etag,\n };\n }\n }\n\n if (!registryResponse.ok) {\n throw new RegistryFetchFailedError(\n registryUrl,\n new Error(`${registryResponse.status} ${registryResponse.statusText}`)\n );\n }\n\n const registryJson = await registryResponse.text();\n const registry = JSON.parse(registryJson) as WalletRegistryV1;\n const etag = registryResponse.headers.get('ETag') || undefined;\n\n // Validate schema\n if (!validateRegistry(registry)) {\n throw new RegistrySchemaInvalidError(\n 'Invalid registry schema',\n { url: registryUrl }\n );\n }\n\n // Fetch signature (skip entirely in dev mode when no public keys)\n let signature: RegistrySignature;\n \n if (requireSignature) {\n // Public keys configured - signature is required\n const sigResponse = await this.fetchFn(sigUrl, {\n headers: {\n 'Accept': 'application/json',\n },\n signal: controller.signal,\n });\n\n if (!sigResponse.ok) {\n throw new RegistryFetchFailedError(\n sigUrl,\n new Error(`${sigResponse.status} ${sigResponse.statusText}`)\n );\n }\n signature = JSON.parse(await sigResponse.text()) as RegistrySignature;\n \n // Verify signature\n const verified = await this.verifyRegistrySignature(registryJson, signature);\n if (!verified) {\n throw new RegistryVerificationFailedError(\n 'Signature verification failed',\n { url: registryUrl }\n );\n }\n } else {\n // Dev mode: skip signature fetch entirely, create dummy signature\n console.log('[RegistryClient] Dev mode: skipping signature fetch (no public keys configured)');\n signature = { algorithm: 'ed25519', signature: '', keyFingerprint: '', signedAt: new Date().toISOString() };\n }\n\n // Check sequence number (prevent downgrades)\n if (this.memoryCache.lastKnownGood) {\n if (registry.metadata.sequence < this.memoryCache.lastKnownGood.sequence) {\n throw new RegistryVerificationFailedError(\n `Sequence downgrade detected: ${registry.metadata.sequence} < ${this.memoryCache.lastKnownGood.sequence}`,\n { url: registryUrl }\n );\n }\n }\n\n return { registry, signature, etag };\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n /**\n * Get registry with SWR pattern\n * - Returns cached immediately if available\n * - Refreshes in background\n */\n async getRegistry(): Promise<WalletRegistryV1> {\n // Return cached immediately if available\n if (this.memoryCache.lastKnownGood) {\n const now = Date.now();\n const age = now - this.memoryCache.lastKnownGood.fetchedAt;\n\n // If cache is fresh, return it\n if (age < this.cacheTtl) {\n // Trigger background refresh if not already refreshing\n if (!this.memoryCache.refreshPromise) {\n this.memoryCache.refreshPromise = this.refreshRegistry();\n }\n return this.memoryCache.lastKnownGood.registry;\n }\n\n // Cache is stale but usable\n if (age < this.staleTtl) {\n // Trigger refresh\n if (!this.memoryCache.refreshPromise) {\n this.memoryCache.refreshPromise = this.refreshRegistry();\n }\n return this.memoryCache.lastKnownGood.registry;\n }\n }\n\n // No cache or too stale - fetch synchronously\n return await this.refreshRegistry();\n }\n\n /**\n * Refresh registry from network\n */\n private async refreshRegistry(): Promise<WalletRegistryV1> {\n // If already refreshing, wait for that\n if (this.memoryCache.refreshPromise) {\n return await this.memoryCache.refreshPromise;\n }\n\n const refreshPromise = (async () => {\n try {\n const { registry, etag } = await this.fetchFromNetwork();\n\n console.log('[RegistryClient] Successfully fetched registry:', {\n channel: registry.metadata.channel,\n sequence: registry.metadata.sequence,\n walletCount: registry.wallets.length,\n });\n\n // Update cache\n const cached: CachedRegistry = {\n registry,\n verified: true,\n fetchedAt: Date.now(),\n etag,\n sequence: registry.metadata.sequence,\n };\n\n this.memoryCache.lastKnownGood = cached;\n this.memoryCache.lastAttempt = {\n fetchedAt: Date.now(),\n };\n\n // Update status\n this.updateStatus({\n source: 'network',\n verified: true,\n channel: registry.metadata.channel,\n sequence: registry.metadata.sequence,\n stale: false,\n fetchedAt: cached.fetchedAt,\n etag,\n });\n\n // Persist to storage\n if (this.storage) {\n await this.saveToStorage(cached);\n }\n\n return registry;\n } catch (error) {\n // Update last attempt\n this.memoryCache.lastAttempt = {\n fetchedAt: Date.now(),\n errorCode:\n error instanceof RegistryFetchFailedError\n ? 'REGISTRY_FETCH_FAILED'\n : error instanceof RegistryVerificationFailedError\n ? 'REGISTRY_VERIFICATION_FAILED'\n : error instanceof RegistrySchemaInvalidError\n ? 'REGISTRY_SCHEMA_INVALID'\n : 'UNKNOWN',\n };\n\n // Update status with error\n const lastKnownGood = this.memoryCache.lastKnownGood;\n if (lastKnownGood) {\n const cantonError = error instanceof RegistryFetchFailedError ||\n error instanceof RegistryVerificationFailedError ||\n error instanceof RegistrySchemaInvalidError\n ? error\n : undefined;\n this.updateStatus({\n source: 'cache',\n verified: lastKnownGood.verified,\n channel: lastKnownGood.registry.metadata.channel,\n sequence: lastKnownGood.sequence,\n stale: Date.now() - lastKnownGood.fetchedAt > this.cacheTtl,\n fetchedAt: lastKnownGood.fetchedAt,\n etag: lastKnownGood.etag,\n error: cantonError,\n });\n\n // Return last known good\n return lastKnownGood.registry;\n }\n\n // No cache available - rethrow\n throw error;\n } finally {\n this.memoryCache.refreshPromise = null;\n }\n })();\n\n this.memoryCache.refreshPromise = refreshPromise;\n return await refreshPromise;\n }\n\n /**\n * Update registry status\n */\n private updateStatus(status: RegistryStatus): void {\n this.currentStatus = status;\n }\n\n /**\n * Get current registry status\n */\n getStatus(): RegistryStatus | null {\n if (!this.memoryCache.lastKnownGood) {\n return null;\n }\n\n const now = Date.now();\n const age = now - this.memoryCache.lastKnownGood.fetchedAt;\n\n return {\n source: this.currentStatus?.source || 'cache',\n verified: this.memoryCache.lastKnownGood.verified,\n channel: this.memoryCache.lastKnownGood.registry.metadata.channel,\n sequence: this.memoryCache.lastKnownGood.sequence,\n stale: age > this.cacheTtl,\n fetchedAt: this.memoryCache.lastKnownGood.fetchedAt,\n etag: this.memoryCache.lastKnownGood.etag,\n error: this.currentStatus?.error,\n };\n }\n\n /**\n * Save to persistent storage\n */\n private async saveToStorage(cached: CachedRegistry): Promise<void> {\n if (!this.storage) return;\n\n const key = `registry_${this.channel}`;\n const value = JSON.stringify(cached);\n await this.storage.set(key, value);\n }\n\n /**\n * Load from persistent storage\n */\n private async loadFromStorage(): Promise<void> {\n if (!this.storage) return;\n\n const key = `registry_${this.channel}`;\n const value = await this.storage.get(key);\n if (value) {\n try {\n const cached = JSON.parse(value) as CachedRegistry;\n this.memoryCache.lastKnownGood = cached;\n } catch {\n // Ignore parse errors\n }\n }\n }\n\n /**\n * Get all wallets\n */\n async getWallets(): Promise<WalletInfo[]> {\n const registry = await this.getRegistry();\n return registry.wallets.map((entry) =>\n registryEntryToWalletInfo(entry, registry.metadata.channel)\n );\n }\n\n /**\n * Get wallet by ID\n */\n async getWallet(walletId: string): Promise<WalletInfo> {\n const registry = await this.getRegistry();\n const entry = registry.wallets.find((w) => w.id === walletId);\n\n if (!entry) {\n throw new WalletNotFoundError(walletId);\n }\n\n return registryEntryToWalletInfo(entry, registry.metadata.channel);\n }\n\n /**\n * Get wallet entry (includes adapter config)\n */\n async getWalletEntry(walletId: string): Promise<RegistryWalletEntry> {\n const registry = await this.getRegistry();\n const entry = registry.wallets.find((w) => w.id === walletId);\n\n if (!entry) {\n throw new WalletNotFoundError(walletId);\n }\n\n if (!validateWalletEntry(entry)) {\n throw new RegistrySchemaInvalidError(\n `Invalid wallet entry for ${walletId}`,\n { url: this.getRegistryUrl() }\n );\n }\n\n return entry;\n }\n\n /**\n * Clear cache\n */\n clearCache(): void {\n this.memoryCache.lastKnownGood = null;\n this.memoryCache.lastAttempt = null;\n this.memoryCache.refreshPromise = null;\n this.currentStatus = null;\n\n if (this.storage) {\n this.storage.remove(`registry_${this.channel}`).catch(() => {\n // Ignore errors\n });\n }\n }\n\n /**\n * Check if cache is valid\n */\n isCacheValid(): boolean {\n if (!this.enableCache || !this.memoryCache.lastKnownGood) {\n return false;\n }\n\n const now = Date.now();\n return now - this.memoryCache.lastKnownGood.fetchedAt < this.cacheTtl;\n }\n}\n"]}
|
package/dist/index.mjs
CHANGED
|
@@ -91,6 +91,7 @@ var RegistryClient = class {
|
|
|
91
91
|
staleTtl;
|
|
92
92
|
enableCache;
|
|
93
93
|
fetchFn;
|
|
94
|
+
fetchTimeout;
|
|
94
95
|
storage;
|
|
95
96
|
// In-memory cache
|
|
96
97
|
memoryCache = {
|
|
@@ -116,6 +117,7 @@ var RegistryClient = class {
|
|
|
116
117
|
} else {
|
|
117
118
|
this.fetchFn = fetch;
|
|
118
119
|
}
|
|
120
|
+
this.fetchTimeout = options.fetchTimeout || 8e3;
|
|
119
121
|
this.storage = options.storage;
|
|
120
122
|
if (this.storage) {
|
|
121
123
|
this.loadFromStorage().catch(() => {
|
|
@@ -188,87 +190,96 @@ var RegistryClient = class {
|
|
|
188
190
|
const registryUrl = this.getRegistryUrl();
|
|
189
191
|
const sigUrl = this.getSignatureUrl();
|
|
190
192
|
const requireSignature = this.publicKeys.length > 0;
|
|
191
|
-
const
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
193
|
+
const controller = new AbortController();
|
|
194
|
+
const timeoutId = setTimeout(() => controller.abort(), this.fetchTimeout);
|
|
195
|
+
try {
|
|
196
|
+
const registryResponse = await this.fetchFn(registryUrl, {
|
|
197
|
+
headers: {
|
|
198
|
+
"Accept": "application/json",
|
|
199
|
+
"If-None-Match": this.memoryCache.lastKnownGood?.etag || ""
|
|
200
|
+
},
|
|
201
|
+
signal: controller.signal
|
|
202
|
+
});
|
|
203
|
+
if (registryResponse.status === 304) {
|
|
204
|
+
if (this.memoryCache.lastKnownGood) {
|
|
205
|
+
let signature2;
|
|
206
|
+
if (requireSignature) {
|
|
207
|
+
try {
|
|
208
|
+
const sigResponse = await this.fetchFn(sigUrl, {
|
|
209
|
+
headers: { "Accept": "application/json" },
|
|
210
|
+
signal: controller.signal
|
|
211
|
+
});
|
|
212
|
+
if (sigResponse.ok) {
|
|
213
|
+
signature2 = JSON.parse(await sigResponse.text());
|
|
214
|
+
} else {
|
|
215
|
+
signature2 = { algorithm: "ed25519", signature: "", keyFingerprint: "", signedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
216
|
+
}
|
|
217
|
+
} catch {
|
|
208
218
|
signature2 = { algorithm: "ed25519", signature: "", keyFingerprint: "", signedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
209
219
|
}
|
|
210
|
-
}
|
|
220
|
+
} else {
|
|
211
221
|
signature2 = { algorithm: "ed25519", signature: "", keyFingerprint: "", signedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
212
222
|
}
|
|
213
|
-
|
|
214
|
-
|
|
223
|
+
return {
|
|
224
|
+
registry: this.memoryCache.lastKnownGood.registry,
|
|
225
|
+
signature: signature2,
|
|
226
|
+
etag: this.memoryCache.lastKnownGood.etag
|
|
227
|
+
};
|
|
215
228
|
}
|
|
216
|
-
return {
|
|
217
|
-
registry: this.memoryCache.lastKnownGood.registry,
|
|
218
|
-
signature: signature2,
|
|
219
|
-
etag: this.memoryCache.lastKnownGood.etag
|
|
220
|
-
};
|
|
221
229
|
}
|
|
222
|
-
|
|
223
|
-
if (!registryResponse.ok) {
|
|
224
|
-
throw new RegistryFetchFailedError(
|
|
225
|
-
registryUrl,
|
|
226
|
-
new Error(`${registryResponse.status} ${registryResponse.statusText}`)
|
|
227
|
-
);
|
|
228
|
-
}
|
|
229
|
-
const registryJson = await registryResponse.text();
|
|
230
|
-
const registry = JSON.parse(registryJson);
|
|
231
|
-
const etag = registryResponse.headers.get("ETag") || void 0;
|
|
232
|
-
if (!validateRegistry(registry)) {
|
|
233
|
-
throw new RegistrySchemaInvalidError(
|
|
234
|
-
"Invalid registry schema",
|
|
235
|
-
{ url: registryUrl }
|
|
236
|
-
);
|
|
237
|
-
}
|
|
238
|
-
let signature;
|
|
239
|
-
if (requireSignature) {
|
|
240
|
-
const sigResponse = await this.fetchFn(sigUrl, {
|
|
241
|
-
headers: {
|
|
242
|
-
"Accept": "application/json"
|
|
243
|
-
}
|
|
244
|
-
});
|
|
245
|
-
if (!sigResponse.ok) {
|
|
230
|
+
if (!registryResponse.ok) {
|
|
246
231
|
throw new RegistryFetchFailedError(
|
|
247
|
-
|
|
248
|
-
new Error(`${
|
|
232
|
+
registryUrl,
|
|
233
|
+
new Error(`${registryResponse.status} ${registryResponse.statusText}`)
|
|
249
234
|
);
|
|
250
235
|
}
|
|
251
|
-
|
|
252
|
-
const
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
236
|
+
const registryJson = await registryResponse.text();
|
|
237
|
+
const registry = JSON.parse(registryJson);
|
|
238
|
+
const etag = registryResponse.headers.get("ETag") || void 0;
|
|
239
|
+
if (!validateRegistry(registry)) {
|
|
240
|
+
throw new RegistrySchemaInvalidError(
|
|
241
|
+
"Invalid registry schema",
|
|
256
242
|
{ url: registryUrl }
|
|
257
243
|
);
|
|
258
244
|
}
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
245
|
+
let signature;
|
|
246
|
+
if (requireSignature) {
|
|
247
|
+
const sigResponse = await this.fetchFn(sigUrl, {
|
|
248
|
+
headers: {
|
|
249
|
+
"Accept": "application/json"
|
|
250
|
+
},
|
|
251
|
+
signal: controller.signal
|
|
252
|
+
});
|
|
253
|
+
if (!sigResponse.ok) {
|
|
254
|
+
throw new RegistryFetchFailedError(
|
|
255
|
+
sigUrl,
|
|
256
|
+
new Error(`${sigResponse.status} ${sigResponse.statusText}`)
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
signature = JSON.parse(await sigResponse.text());
|
|
260
|
+
const verified = await this.verifyRegistrySignature(registryJson, signature);
|
|
261
|
+
if (!verified) {
|
|
262
|
+
throw new RegistryVerificationFailedError(
|
|
263
|
+
"Signature verification failed",
|
|
264
|
+
{ url: registryUrl }
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
} else {
|
|
268
|
+
console.log("[RegistryClient] Dev mode: skipping signature fetch (no public keys configured)");
|
|
269
|
+
signature = { algorithm: "ed25519", signature: "", keyFingerprint: "", signedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
270
|
+
}
|
|
271
|
+
if (this.memoryCache.lastKnownGood) {
|
|
272
|
+
if (registry.metadata.sequence < this.memoryCache.lastKnownGood.sequence) {
|
|
273
|
+
throw new RegistryVerificationFailedError(
|
|
274
|
+
`Sequence downgrade detected: ${registry.metadata.sequence} < ${this.memoryCache.lastKnownGood.sequence}`,
|
|
275
|
+
{ url: registryUrl }
|
|
276
|
+
);
|
|
277
|
+
}
|
|
269
278
|
}
|
|
279
|
+
return { registry, signature, etag };
|
|
280
|
+
} finally {
|
|
281
|
+
clearTimeout(timeoutId);
|
|
270
282
|
}
|
|
271
|
-
return { registry, signature, etag };
|
|
272
283
|
}
|
|
273
284
|
/**
|
|
274
285
|
* Get registry with SWR pattern
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/schema.ts","../src/client.ts"],"names":["signature"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Wallet Registry Schema v1\n * \n * This schema defines the structure of the wallet registry JSON.\n * The registry is versioned and supports:\n * - Multiple wallet entries\n * - Versioning and rollback\n * - Integrity checks (Ed25519 signatures)\n * - Multi-channel (stable/beta)\n * - Forward compatibility\n * \n * References:\n * - Wallet Integration Guide: https://docs.digitalasset.com/integrate/devnet/index.html\n */\n\nimport type { WalletInfo, NetworkId, CapabilityKey } from '@partylayer/core';\nimport { toWalletId } from '@partylayer/core';\n\n/**\n * Registry schema version\n */\nexport const REGISTRY_SCHEMA_VERSION = '1.0.0';\n\n/**\n * Registry channel\n */\nexport type RegistryChannel = 'stable' | 'beta';\n\n/**\n * Wallet entry in registry\n */\nexport interface RegistryWalletEntry {\n /** Wallet identifier (must be unique within channel) */\n id: string;\n /** Display name */\n name: string;\n /** Short description */\n description?: string;\n /** Homepage URL */\n homepage?: string;\n /** Icon URL (should be absolute) */\n icon?: string;\n /** Supported networks */\n supportedNetworks: NetworkId[];\n /** Wallet capabilities */\n capabilities: {\n signMessage: boolean;\n signTransaction: boolean;\n submitTransaction: boolean;\n transactionStatus: boolean;\n switchNetwork: boolean;\n multiParty: boolean;\n };\n /** Adapter configuration */\n adapter: {\n /** Adapter type/name */\n type: string;\n /** Adapter-specific configuration */\n config?: Record<string, unknown>;\n };\n /** Installation detection hints */\n installation?: {\n /** Check if wallet is installed via window property */\n windowProperty?: string;\n /** Check if wallet is installed via script tag */\n scriptTag?: string;\n /** Check if wallet is installed via browser extension */\n extensionId?: string;\n };\n /** SDK version compatibility */\n sdkVersion?: string;\n /** Metadata version (for cache invalidation) */\n version?: string;\n /** Origin allowlist (optional - if present, only these origins can connect) */\n originAllowlist?: string[];\n}\n\n/**\n * Registry metadata\n */\nexport interface RegistryMetadata {\n /** Registry version (semver) */\n registryVersion: string;\n /** Schema version */\n schemaVersion: string;\n /** ISO 8601 timestamp when registry was published */\n publishedAt: string;\n /** Channel (stable or beta) */\n channel: RegistryChannel;\n /** Monotonic sequence number (increments on each update) */\n sequence: number;\n /** Registry publisher */\n publisher?: string;\n}\n\n/**\n * Wallet Registry v1 structure\n * \n * Note: Signature is NOT embedded. It's in a separate .sig file.\n */\nexport interface WalletRegistryV1 {\n /** Registry metadata */\n metadata: RegistryMetadata;\n /** Array of wallet entries */\n wallets: RegistryWalletEntry[];\n}\n\n/**\n * Registry signature file format\n * \n * This is stored separately as registry.sig\n */\nexport interface RegistrySignature {\n /** Signature algorithm (always 'ed25519') */\n algorithm: 'ed25519';\n /** Signature value (base64-encoded) */\n signature: string;\n /** Public key fingerprint (for key identification) */\n keyFingerprint: string;\n /** Timestamp when signed */\n signedAt: string;\n}\n\n/**\n * Validate registry structure\n */\nexport function validateRegistry(\n registry: unknown\n): registry is WalletRegistryV1 {\n if (typeof registry !== 'object' || registry === null) {\n return false;\n }\n\n const r = registry as Record<string, unknown>;\n\n // Check metadata\n if (!r.metadata || typeof r.metadata !== 'object') {\n return false;\n }\n\n const metadata = r.metadata as Record<string, unknown>;\n if (\n typeof metadata.registryVersion !== 'string' ||\n typeof metadata.schemaVersion !== 'string' ||\n typeof metadata.publishedAt !== 'string' ||\n typeof metadata.channel !== 'string' ||\n (metadata.channel !== 'stable' && metadata.channel !== 'beta') ||\n typeof metadata.sequence !== 'number' ||\n !Number.isInteger(metadata.sequence) ||\n metadata.sequence < 0\n ) {\n return false;\n }\n\n // Check wallets array\n if (!Array.isArray(r.wallets)) {\n return false;\n }\n\n // Validate each wallet entry\n const walletIds = new Set<string>();\n for (const wallet of r.wallets) {\n if (!validateWalletEntry(wallet)) {\n return false;\n }\n // Check uniqueness\n const entry = wallet as RegistryWalletEntry;\n if (walletIds.has(entry.id)) {\n return false;\n }\n walletIds.add(entry.id);\n }\n\n return true;\n}\n\n/**\n * Validate wallet entry\n */\nexport function validateWalletEntry(\n entry: unknown\n): entry is RegistryWalletEntry {\n if (typeof entry !== 'object' || entry === null) {\n return false;\n }\n\n const e = entry as Record<string, unknown>;\n\n return (\n typeof e.id === 'string' &&\n typeof e.name === 'string' &&\n Array.isArray(e.supportedNetworks) &&\n typeof e.capabilities === 'object' &&\n e.capabilities !== null &&\n typeof e.adapter === 'object' &&\n e.adapter !== null &&\n typeof (e.adapter as Record<string, unknown>).type === 'string' &&\n (e.originAllowlist === undefined || Array.isArray(e.originAllowlist))\n );\n}\n\n/**\n * Convert registry entry to wallet info\n */\nexport function registryEntryToWalletInfo(\n entry: RegistryWalletEntry,\n channel: RegistryChannel\n): WalletInfo {\n const capabilities: CapabilityKey[] = ['connect', 'disconnect'];\n if (entry.capabilities.signMessage) {\n capabilities.push('signMessage');\n }\n if (entry.capabilities.signTransaction) {\n capabilities.push('signTransaction');\n }\n if (entry.capabilities.submitTransaction) {\n capabilities.push('submitTransaction');\n }\n if (entry.capabilities.transactionStatus) {\n capabilities.push('events');\n }\n\n return {\n walletId: toWalletId(entry.id),\n name: entry.name,\n website: entry.homepage || '',\n icons: {\n sm: entry.icon,\n md: entry.icon,\n lg: entry.icon,\n },\n category: 'browser',\n capabilities,\n installHints: entry.installation\n ? {\n injectedKey: entry.installation.windowProperty,\n extensionId: entry.installation.extensionId,\n deepLinkScheme: entry.installation.scriptTag,\n }\n : undefined,\n adapter: {\n packageName: entry.adapter.type,\n versionRange: entry.sdkVersion || '*',\n },\n docs: entry.homepage ? [entry.homepage] : [],\n minSdkVersion: entry.sdkVersion,\n networks: entry.supportedNetworks,\n channel,\n // Store origin allowlist in metadata for SDK enforcement\n ...(entry.originAllowlist\n ? { metadata: { originAllowlist: JSON.stringify(entry.originAllowlist) } }\n : {}),\n };\n}\n\n/**\n * @deprecated Use registryEntryToWalletInfo instead\n */\nexport function registryEntryToMetadata(\n entry: RegistryWalletEntry\n): WalletInfo {\n return registryEntryToWalletInfo(entry, 'stable');\n}\n","/**\n * Registry client for fetching and caching wallet registry\n * \n * Features:\n * - Ed25519 signature verification\n * - Multi-channel support (stable/beta)\n * - Sequence number validation (prevents downgrades)\n * - Last-known-good caching\n * - SWR pattern (serve cached immediately, refresh in background)\n * - ETag support for efficient updates\n * \n * References:\n * - Wallet Integration Guide: https://docs.digitalasset.com/integrate/devnet/index.html\n */\n\nimport type { WalletInfo } from '@partylayer/core';\nimport {\n RegistryFetchFailedError,\n RegistryVerificationFailedError,\n RegistrySchemaInvalidError,\n WalletNotFoundError,\n} from '@partylayer/core';\nimport type {\n WalletRegistryV1,\n RegistryWalletEntry,\n RegistryChannel,\n RegistrySignature,\n} from './schema';\nimport {\n validateRegistry,\n validateWalletEntry,\n registryEntryToWalletInfo,\n} from './schema';\nimport type { RegistryStatus, CachedRegistry, LastFetchAttempt } from './status';\n\n/**\n * Registry client options\n */\nexport interface RegistryClientOptions {\n /** Base registry URL (client appends /v1/{channel}/registry.json) */\n registryUrl?: string;\n /** Registry channel */\n channel?: RegistryChannel;\n /** Public keys for signature verification (base64) */\n registryPublicKeys?: string[];\n /** Cache TTL in milliseconds (default: 1 hour) */\n cacheTtl?: number;\n /** Stale TTL in milliseconds (default: 24 hours - cache usable but marked stale) */\n staleTtl?: number;\n /** Enable cache (default: true) */\n enableCache?: boolean;\n /** Custom fetch function */\n fetch?: typeof fetch;\n /** Storage adapter for persistent cache */\n storage?: {\n get(key: string): Promise<string | null>;\n set(key: string, value: string): Promise<void>;\n remove(key: string): Promise<void>;\n };\n}\n\n/**\n * Default registry URL\n */\nconst DEFAULT_REGISTRY_URL = 'https://registry.partylayer.xyz';\n\n/**\n * Registry client\n */\nexport class RegistryClient {\n private baseUrl: string;\n private channel: RegistryChannel;\n private publicKeys: string[];\n private cacheTtl: number;\n private staleTtl: number;\n private enableCache: boolean;\n private fetchFn: typeof fetch;\n private storage?: RegistryClientOptions['storage'];\n\n // In-memory cache\n private memoryCache: {\n lastKnownGood: CachedRegistry | null;\n lastAttempt: LastFetchAttempt | null;\n refreshPromise: Promise<WalletRegistryV1> | null;\n } = {\n lastKnownGood: null,\n lastAttempt: null,\n refreshPromise: null,\n };\n\n // Status tracking\n private currentStatus: RegistryStatus | null = null;\n\n constructor(options: RegistryClientOptions = {}) {\n this.baseUrl = options.registryUrl || DEFAULT_REGISTRY_URL;\n this.channel = options.channel || 'stable';\n this.publicKeys = options.registryPublicKeys || [];\n this.cacheTtl = options.cacheTtl || 60 * 60 * 1000; // 1 hour\n this.staleTtl = options.staleTtl || 24 * 60 * 60 * 1000; // 24 hours\n this.enableCache = options.enableCache !== false;\n // Bind fetch to prevent \"Illegal invocation\" error\n // Use global fetch directly to avoid context issues\n if (options.fetch) {\n this.fetchFn = options.fetch;\n } else if (typeof window !== 'undefined' && window.fetch) {\n this.fetchFn = window.fetch.bind(window);\n } else if (typeof globalThis !== 'undefined' && globalThis.fetch) {\n this.fetchFn = globalThis.fetch.bind(globalThis);\n } else {\n this.fetchFn = fetch;\n }\n this.storage = options.storage;\n\n // Load from persistent storage if available\n if (this.storage) {\n this.loadFromStorage().catch(() => {\n // Ignore errors on load\n });\n }\n }\n\n /**\n * Get registry URL for channel\n */\n private getRegistryUrl(): string {\n return `${this.baseUrl}/v1/${this.channel}/registry.json`;\n }\n\n /**\n * Get signature URL for channel\n */\n private getSignatureUrl(): string {\n return `${this.baseUrl}/v1/${this.channel}/registry.sig`;\n }\n\n /**\n * Import public key from base64\n */\n private async importPublicKey(keyBase64: string): Promise<CryptoKey> {\n const keyBuffer = Buffer.from(keyBase64, 'base64');\n return await crypto.subtle.importKey(\n 'raw',\n keyBuffer,\n {\n name: 'Ed25519',\n namedCurve: 'Ed25519',\n },\n true,\n ['verify']\n );\n }\n\n /**\n * Verify signature\n */\n private async verifySignature(\n registryJson: string,\n signature: RegistrySignature,\n publicKey: CryptoKey\n ): Promise<boolean> {\n if (signature.algorithm !== 'ed25519') {\n return false;\n }\n\n const data = new TextEncoder().encode(registryJson);\n const sigBuffer = Buffer.from(signature.signature, 'base64');\n return await crypto.subtle.verify('Ed25519', publicKey, sigBuffer, data);\n }\n\n /**\n * Verify registry signature\n */\n private async verifyRegistrySignature(\n registryJson: string,\n signature: RegistrySignature\n ): Promise<boolean> {\n if (this.publicKeys.length === 0) {\n // No public keys configured - skip verification (dev mode)\n return true;\n }\n\n // Try each public key\n for (const pubkeyBase64 of this.publicKeys) {\n try {\n const publicKey = await this.importPublicKey(pubkeyBase64);\n const isValid = await this.verifySignature(registryJson, signature, publicKey);\n if (isValid) {\n return true;\n }\n } catch {\n // Try next key\n continue;\n }\n }\n\n return false;\n }\n\n /**\n * Fetch registry and signature from network\n */\n private async fetchFromNetwork(): Promise<{\n registry: WalletRegistryV1;\n signature: RegistrySignature;\n etag?: string;\n }> {\n const registryUrl = this.getRegistryUrl();\n const sigUrl = this.getSignatureUrl();\n const requireSignature = this.publicKeys.length > 0;\n\n // Fetch registry (always required)\n const registryResponse = await this.fetchFn(registryUrl, {\n headers: {\n 'Accept': 'application/json',\n 'If-None-Match': this.memoryCache.lastKnownGood?.etag || '',\n },\n });\n\n // Handle 304 Not Modified\n if (registryResponse.status === 304) {\n if (this.memoryCache.lastKnownGood) {\n // For 304, we still need a signature object for return type\n // In dev mode, create dummy signature (skip fetch entirely)\n let signature: RegistrySignature;\n if (requireSignature) {\n // Production mode: try to fetch signature\n try {\n const sigResponse = await this.fetchFn(sigUrl, {\n headers: { 'Accept': 'application/json' },\n });\n if (sigResponse.ok) {\n signature = JSON.parse(await sigResponse.text()) as RegistrySignature;\n } else {\n // Signature missing but we have cache - use dummy\n signature = { algorithm: 'ed25519', signature: '', keyFingerprint: '', signedAt: new Date().toISOString() };\n }\n } catch {\n signature = { algorithm: 'ed25519', signature: '', keyFingerprint: '', signedAt: new Date().toISOString() };\n }\n } else {\n // Dev mode: create dummy signature\n signature = { algorithm: 'ed25519', signature: '', keyFingerprint: '', signedAt: new Date().toISOString() };\n }\n \n return {\n registry: this.memoryCache.lastKnownGood.registry,\n signature,\n etag: this.memoryCache.lastKnownGood.etag,\n };\n }\n }\n\n if (!registryResponse.ok) {\n throw new RegistryFetchFailedError(\n registryUrl,\n new Error(`${registryResponse.status} ${registryResponse.statusText}`)\n );\n }\n\n const registryJson = await registryResponse.text();\n const registry = JSON.parse(registryJson) as WalletRegistryV1;\n const etag = registryResponse.headers.get('ETag') || undefined;\n\n // Validate schema\n if (!validateRegistry(registry)) {\n throw new RegistrySchemaInvalidError(\n 'Invalid registry schema',\n { url: registryUrl }\n );\n }\n\n // Fetch signature (skip entirely in dev mode when no public keys)\n let signature: RegistrySignature;\n \n if (requireSignature) {\n // Public keys configured - signature is required\n const sigResponse = await this.fetchFn(sigUrl, {\n headers: {\n 'Accept': 'application/json',\n },\n });\n\n if (!sigResponse.ok) {\n throw new RegistryFetchFailedError(\n sigUrl,\n new Error(`${sigResponse.status} ${sigResponse.statusText}`)\n );\n }\n signature = JSON.parse(await sigResponse.text()) as RegistrySignature;\n \n // Verify signature\n const verified = await this.verifyRegistrySignature(registryJson, signature);\n if (!verified) {\n throw new RegistryVerificationFailedError(\n 'Signature verification failed',\n { url: registryUrl }\n );\n }\n } else {\n // Dev mode: skip signature fetch entirely, create dummy signature\n console.log('[RegistryClient] Dev mode: skipping signature fetch (no public keys configured)');\n signature = { algorithm: 'ed25519', signature: '', keyFingerprint: '', signedAt: new Date().toISOString() };\n }\n\n // Check sequence number (prevent downgrades)\n if (this.memoryCache.lastKnownGood) {\n if (registry.metadata.sequence < this.memoryCache.lastKnownGood.sequence) {\n throw new RegistryVerificationFailedError(\n `Sequence downgrade detected: ${registry.metadata.sequence} < ${this.memoryCache.lastKnownGood.sequence}`,\n { url: registryUrl }\n );\n }\n }\n\n return { registry, signature, etag };\n }\n\n /**\n * Get registry with SWR pattern\n * - Returns cached immediately if available\n * - Refreshes in background\n */\n async getRegistry(): Promise<WalletRegistryV1> {\n // Return cached immediately if available\n if (this.memoryCache.lastKnownGood) {\n const now = Date.now();\n const age = now - this.memoryCache.lastKnownGood.fetchedAt;\n\n // If cache is fresh, return it\n if (age < this.cacheTtl) {\n // Trigger background refresh if not already refreshing\n if (!this.memoryCache.refreshPromise) {\n this.memoryCache.refreshPromise = this.refreshRegistry();\n }\n return this.memoryCache.lastKnownGood.registry;\n }\n\n // Cache is stale but usable\n if (age < this.staleTtl) {\n // Trigger refresh\n if (!this.memoryCache.refreshPromise) {\n this.memoryCache.refreshPromise = this.refreshRegistry();\n }\n return this.memoryCache.lastKnownGood.registry;\n }\n }\n\n // No cache or too stale - fetch synchronously\n return await this.refreshRegistry();\n }\n\n /**\n * Refresh registry from network\n */\n private async refreshRegistry(): Promise<WalletRegistryV1> {\n // If already refreshing, wait for that\n if (this.memoryCache.refreshPromise) {\n return await this.memoryCache.refreshPromise;\n }\n\n const refreshPromise = (async () => {\n try {\n const { registry, etag } = await this.fetchFromNetwork();\n\n console.log('[RegistryClient] Successfully fetched registry:', {\n channel: registry.metadata.channel,\n sequence: registry.metadata.sequence,\n walletCount: registry.wallets.length,\n });\n\n // Update cache\n const cached: CachedRegistry = {\n registry,\n verified: true,\n fetchedAt: Date.now(),\n etag,\n sequence: registry.metadata.sequence,\n };\n\n this.memoryCache.lastKnownGood = cached;\n this.memoryCache.lastAttempt = {\n fetchedAt: Date.now(),\n };\n\n // Update status\n this.updateStatus({\n source: 'network',\n verified: true,\n channel: registry.metadata.channel,\n sequence: registry.metadata.sequence,\n stale: false,\n fetchedAt: cached.fetchedAt,\n etag,\n });\n\n // Persist to storage\n if (this.storage) {\n await this.saveToStorage(cached);\n }\n\n return registry;\n } catch (error) {\n // Update last attempt\n this.memoryCache.lastAttempt = {\n fetchedAt: Date.now(),\n errorCode:\n error instanceof RegistryFetchFailedError\n ? 'REGISTRY_FETCH_FAILED'\n : error instanceof RegistryVerificationFailedError\n ? 'REGISTRY_VERIFICATION_FAILED'\n : error instanceof RegistrySchemaInvalidError\n ? 'REGISTRY_SCHEMA_INVALID'\n : 'UNKNOWN',\n };\n\n // Update status with error\n const lastKnownGood = this.memoryCache.lastKnownGood;\n if (lastKnownGood) {\n const cantonError = error instanceof RegistryFetchFailedError ||\n error instanceof RegistryVerificationFailedError ||\n error instanceof RegistrySchemaInvalidError\n ? error\n : undefined;\n this.updateStatus({\n source: 'cache',\n verified: lastKnownGood.verified,\n channel: lastKnownGood.registry.metadata.channel,\n sequence: lastKnownGood.sequence,\n stale: Date.now() - lastKnownGood.fetchedAt > this.cacheTtl,\n fetchedAt: lastKnownGood.fetchedAt,\n etag: lastKnownGood.etag,\n error: cantonError,\n });\n\n // Return last known good\n return lastKnownGood.registry;\n }\n\n // No cache available - rethrow\n throw error;\n } finally {\n this.memoryCache.refreshPromise = null;\n }\n })();\n\n this.memoryCache.refreshPromise = refreshPromise;\n return await refreshPromise;\n }\n\n /**\n * Update registry status\n */\n private updateStatus(status: RegistryStatus): void {\n this.currentStatus = status;\n }\n\n /**\n * Get current registry status\n */\n getStatus(): RegistryStatus | null {\n if (!this.memoryCache.lastKnownGood) {\n return null;\n }\n\n const now = Date.now();\n const age = now - this.memoryCache.lastKnownGood.fetchedAt;\n\n return {\n source: this.currentStatus?.source || 'cache',\n verified: this.memoryCache.lastKnownGood.verified,\n channel: this.memoryCache.lastKnownGood.registry.metadata.channel,\n sequence: this.memoryCache.lastKnownGood.sequence,\n stale: age > this.cacheTtl,\n fetchedAt: this.memoryCache.lastKnownGood.fetchedAt,\n etag: this.memoryCache.lastKnownGood.etag,\n error: this.currentStatus?.error,\n };\n }\n\n /**\n * Save to persistent storage\n */\n private async saveToStorage(cached: CachedRegistry): Promise<void> {\n if (!this.storage) return;\n\n const key = `registry_${this.channel}`;\n const value = JSON.stringify(cached);\n await this.storage.set(key, value);\n }\n\n /**\n * Load from persistent storage\n */\n private async loadFromStorage(): Promise<void> {\n if (!this.storage) return;\n\n const key = `registry_${this.channel}`;\n const value = await this.storage.get(key);\n if (value) {\n try {\n const cached = JSON.parse(value) as CachedRegistry;\n this.memoryCache.lastKnownGood = cached;\n } catch {\n // Ignore parse errors\n }\n }\n }\n\n /**\n * Get all wallets\n */\n async getWallets(): Promise<WalletInfo[]> {\n const registry = await this.getRegistry();\n return registry.wallets.map((entry) =>\n registryEntryToWalletInfo(entry, registry.metadata.channel)\n );\n }\n\n /**\n * Get wallet by ID\n */\n async getWallet(walletId: string): Promise<WalletInfo> {\n const registry = await this.getRegistry();\n const entry = registry.wallets.find((w) => w.id === walletId);\n\n if (!entry) {\n throw new WalletNotFoundError(walletId);\n }\n\n return registryEntryToWalletInfo(entry, registry.metadata.channel);\n }\n\n /**\n * Get wallet entry (includes adapter config)\n */\n async getWalletEntry(walletId: string): Promise<RegistryWalletEntry> {\n const registry = await this.getRegistry();\n const entry = registry.wallets.find((w) => w.id === walletId);\n\n if (!entry) {\n throw new WalletNotFoundError(walletId);\n }\n\n if (!validateWalletEntry(entry)) {\n throw new RegistrySchemaInvalidError(\n `Invalid wallet entry for ${walletId}`,\n { url: this.getRegistryUrl() }\n );\n }\n\n return entry;\n }\n\n /**\n * Clear cache\n */\n clearCache(): void {\n this.memoryCache.lastKnownGood = null;\n this.memoryCache.lastAttempt = null;\n this.memoryCache.refreshPromise = null;\n this.currentStatus = null;\n\n if (this.storage) {\n this.storage.remove(`registry_${this.channel}`).catch(() => {\n // Ignore errors\n });\n }\n }\n\n /**\n * Check if cache is valid\n */\n isCacheValid(): boolean {\n if (!this.enableCache || !this.memoryCache.lastKnownGood) {\n return false;\n }\n\n const now = Date.now();\n return now - this.memoryCache.lastKnownGood.fetchedAt < this.cacheTtl;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/schema.ts","../src/client.ts"],"names":["signature"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Wallet Registry Schema v1\n * \n * This schema defines the structure of the wallet registry JSON.\n * The registry is versioned and supports:\n * - Multiple wallet entries\n * - Versioning and rollback\n * - Integrity checks (Ed25519 signatures)\n * - Multi-channel (stable/beta)\n * - Forward compatibility\n * \n * References:\n * - Wallet Integration Guide: https://docs.digitalasset.com/integrate/devnet/index.html\n */\n\nimport type { WalletInfo, NetworkId, CapabilityKey } from '@partylayer/core';\nimport { toWalletId } from '@partylayer/core';\n\n/**\n * Registry schema version\n */\nexport const REGISTRY_SCHEMA_VERSION = '1.0.0';\n\n/**\n * Registry channel\n */\nexport type RegistryChannel = 'stable' | 'beta';\n\n/**\n * Wallet entry in registry\n */\nexport interface RegistryWalletEntry {\n /** Wallet identifier (must be unique within channel) */\n id: string;\n /** Display name */\n name: string;\n /** Short description */\n description?: string;\n /** Homepage URL */\n homepage?: string;\n /** Icon URL (should be absolute) */\n icon?: string;\n /** Supported networks */\n supportedNetworks: NetworkId[];\n /** Wallet capabilities */\n capabilities: {\n signMessage: boolean;\n signTransaction: boolean;\n submitTransaction: boolean;\n transactionStatus: boolean;\n switchNetwork: boolean;\n multiParty: boolean;\n };\n /** Adapter configuration */\n adapter: {\n /** Adapter type/name */\n type: string;\n /** Adapter-specific configuration */\n config?: Record<string, unknown>;\n };\n /** Installation detection hints */\n installation?: {\n /** Check if wallet is installed via window property */\n windowProperty?: string;\n /** Check if wallet is installed via script tag */\n scriptTag?: string;\n /** Check if wallet is installed via browser extension */\n extensionId?: string;\n };\n /** SDK version compatibility */\n sdkVersion?: string;\n /** Metadata version (for cache invalidation) */\n version?: string;\n /** Origin allowlist (optional - if present, only these origins can connect) */\n originAllowlist?: string[];\n}\n\n/**\n * Registry metadata\n */\nexport interface RegistryMetadata {\n /** Registry version (semver) */\n registryVersion: string;\n /** Schema version */\n schemaVersion: string;\n /** ISO 8601 timestamp when registry was published */\n publishedAt: string;\n /** Channel (stable or beta) */\n channel: RegistryChannel;\n /** Monotonic sequence number (increments on each update) */\n sequence: number;\n /** Registry publisher */\n publisher?: string;\n}\n\n/**\n * Wallet Registry v1 structure\n * \n * Note: Signature is NOT embedded. It's in a separate .sig file.\n */\nexport interface WalletRegistryV1 {\n /** Registry metadata */\n metadata: RegistryMetadata;\n /** Array of wallet entries */\n wallets: RegistryWalletEntry[];\n}\n\n/**\n * Registry signature file format\n * \n * This is stored separately as registry.sig\n */\nexport interface RegistrySignature {\n /** Signature algorithm (always 'ed25519') */\n algorithm: 'ed25519';\n /** Signature value (base64-encoded) */\n signature: string;\n /** Public key fingerprint (for key identification) */\n keyFingerprint: string;\n /** Timestamp when signed */\n signedAt: string;\n}\n\n/**\n * Validate registry structure\n */\nexport function validateRegistry(\n registry: unknown\n): registry is WalletRegistryV1 {\n if (typeof registry !== 'object' || registry === null) {\n return false;\n }\n\n const r = registry as Record<string, unknown>;\n\n // Check metadata\n if (!r.metadata || typeof r.metadata !== 'object') {\n return false;\n }\n\n const metadata = r.metadata as Record<string, unknown>;\n if (\n typeof metadata.registryVersion !== 'string' ||\n typeof metadata.schemaVersion !== 'string' ||\n typeof metadata.publishedAt !== 'string' ||\n typeof metadata.channel !== 'string' ||\n (metadata.channel !== 'stable' && metadata.channel !== 'beta') ||\n typeof metadata.sequence !== 'number' ||\n !Number.isInteger(metadata.sequence) ||\n metadata.sequence < 0\n ) {\n return false;\n }\n\n // Check wallets array\n if (!Array.isArray(r.wallets)) {\n return false;\n }\n\n // Validate each wallet entry\n const walletIds = new Set<string>();\n for (const wallet of r.wallets) {\n if (!validateWalletEntry(wallet)) {\n return false;\n }\n // Check uniqueness\n const entry = wallet as RegistryWalletEntry;\n if (walletIds.has(entry.id)) {\n return false;\n }\n walletIds.add(entry.id);\n }\n\n return true;\n}\n\n/**\n * Validate wallet entry\n */\nexport function validateWalletEntry(\n entry: unknown\n): entry is RegistryWalletEntry {\n if (typeof entry !== 'object' || entry === null) {\n return false;\n }\n\n const e = entry as Record<string, unknown>;\n\n return (\n typeof e.id === 'string' &&\n typeof e.name === 'string' &&\n Array.isArray(e.supportedNetworks) &&\n typeof e.capabilities === 'object' &&\n e.capabilities !== null &&\n typeof e.adapter === 'object' &&\n e.adapter !== null &&\n typeof (e.adapter as Record<string, unknown>).type === 'string' &&\n (e.originAllowlist === undefined || Array.isArray(e.originAllowlist))\n );\n}\n\n/**\n * Convert registry entry to wallet info\n */\nexport function registryEntryToWalletInfo(\n entry: RegistryWalletEntry,\n channel: RegistryChannel\n): WalletInfo {\n const capabilities: CapabilityKey[] = ['connect', 'disconnect'];\n if (entry.capabilities.signMessage) {\n capabilities.push('signMessage');\n }\n if (entry.capabilities.signTransaction) {\n capabilities.push('signTransaction');\n }\n if (entry.capabilities.submitTransaction) {\n capabilities.push('submitTransaction');\n }\n if (entry.capabilities.transactionStatus) {\n capabilities.push('events');\n }\n\n return {\n walletId: toWalletId(entry.id),\n name: entry.name,\n website: entry.homepage || '',\n icons: {\n sm: entry.icon,\n md: entry.icon,\n lg: entry.icon,\n },\n category: 'browser',\n capabilities,\n installHints: entry.installation\n ? {\n injectedKey: entry.installation.windowProperty,\n extensionId: entry.installation.extensionId,\n deepLinkScheme: entry.installation.scriptTag,\n }\n : undefined,\n adapter: {\n packageName: entry.adapter.type,\n versionRange: entry.sdkVersion || '*',\n },\n docs: entry.homepage ? [entry.homepage] : [],\n minSdkVersion: entry.sdkVersion,\n networks: entry.supportedNetworks,\n channel,\n // Store origin allowlist in metadata for SDK enforcement\n ...(entry.originAllowlist\n ? { metadata: { originAllowlist: JSON.stringify(entry.originAllowlist) } }\n : {}),\n };\n}\n\n/**\n * @deprecated Use registryEntryToWalletInfo instead\n */\nexport function registryEntryToMetadata(\n entry: RegistryWalletEntry\n): WalletInfo {\n return registryEntryToWalletInfo(entry, 'stable');\n}\n","/**\n * Registry client for fetching and caching wallet registry\n * \n * Features:\n * - Ed25519 signature verification\n * - Multi-channel support (stable/beta)\n * - Sequence number validation (prevents downgrades)\n * - Last-known-good caching\n * - SWR pattern (serve cached immediately, refresh in background)\n * - ETag support for efficient updates\n * \n * References:\n * - Wallet Integration Guide: https://docs.digitalasset.com/integrate/devnet/index.html\n */\n\nimport type { WalletInfo } from '@partylayer/core';\nimport {\n RegistryFetchFailedError,\n RegistryVerificationFailedError,\n RegistrySchemaInvalidError,\n WalletNotFoundError,\n} from '@partylayer/core';\nimport type {\n WalletRegistryV1,\n RegistryWalletEntry,\n RegistryChannel,\n RegistrySignature,\n} from './schema';\nimport {\n validateRegistry,\n validateWalletEntry,\n registryEntryToWalletInfo,\n} from './schema';\nimport type { RegistryStatus, CachedRegistry, LastFetchAttempt } from './status';\n\n/**\n * Registry client options\n */\nexport interface RegistryClientOptions {\n /** Base registry URL (client appends /v1/{channel}/registry.json) */\n registryUrl?: string;\n /** Registry channel */\n channel?: RegistryChannel;\n /** Public keys for signature verification (base64) */\n registryPublicKeys?: string[];\n /** Cache TTL in milliseconds (default: 1 hour) */\n cacheTtl?: number;\n /** Stale TTL in milliseconds (default: 24 hours - cache usable but marked stale) */\n staleTtl?: number;\n /** Enable cache (default: true) */\n enableCache?: boolean;\n /** Custom fetch function */\n fetch?: typeof fetch;\n /** Fetch timeout in milliseconds (default: 8000) */\n fetchTimeout?: number;\n /** Storage adapter for persistent cache */\n storage?: {\n get(key: string): Promise<string | null>;\n set(key: string, value: string): Promise<void>;\n remove(key: string): Promise<void>;\n };\n}\n\n/**\n * Default registry URL\n */\nconst DEFAULT_REGISTRY_URL = 'https://registry.partylayer.xyz';\n\n/**\n * Registry client\n */\nexport class RegistryClient {\n private baseUrl: string;\n private channel: RegistryChannel;\n private publicKeys: string[];\n private cacheTtl: number;\n private staleTtl: number;\n private enableCache: boolean;\n private fetchFn: typeof fetch;\n private fetchTimeout: number;\n private storage?: RegistryClientOptions['storage'];\n\n // In-memory cache\n private memoryCache: {\n lastKnownGood: CachedRegistry | null;\n lastAttempt: LastFetchAttempt | null;\n refreshPromise: Promise<WalletRegistryV1> | null;\n } = {\n lastKnownGood: null,\n lastAttempt: null,\n refreshPromise: null,\n };\n\n // Status tracking\n private currentStatus: RegistryStatus | null = null;\n\n constructor(options: RegistryClientOptions = {}) {\n this.baseUrl = options.registryUrl || DEFAULT_REGISTRY_URL;\n this.channel = options.channel || 'stable';\n this.publicKeys = options.registryPublicKeys || [];\n this.cacheTtl = options.cacheTtl || 60 * 60 * 1000; // 1 hour\n this.staleTtl = options.staleTtl || 24 * 60 * 60 * 1000; // 24 hours\n this.enableCache = options.enableCache !== false;\n // Bind fetch to prevent \"Illegal invocation\" error\n // Use global fetch directly to avoid context issues\n if (options.fetch) {\n this.fetchFn = options.fetch;\n } else if (typeof window !== 'undefined' && window.fetch) {\n this.fetchFn = window.fetch.bind(window);\n } else if (typeof globalThis !== 'undefined' && globalThis.fetch) {\n this.fetchFn = globalThis.fetch.bind(globalThis);\n } else {\n this.fetchFn = fetch;\n }\n this.fetchTimeout = options.fetchTimeout || 8000;\n this.storage = options.storage;\n\n // Load from persistent storage if available\n if (this.storage) {\n this.loadFromStorage().catch(() => {\n // Ignore errors on load\n });\n }\n }\n\n /**\n * Get registry URL for channel\n */\n private getRegistryUrl(): string {\n return `${this.baseUrl}/v1/${this.channel}/registry.json`;\n }\n\n /**\n * Get signature URL for channel\n */\n private getSignatureUrl(): string {\n return `${this.baseUrl}/v1/${this.channel}/registry.sig`;\n }\n\n /**\n * Import public key from base64\n */\n private async importPublicKey(keyBase64: string): Promise<CryptoKey> {\n const keyBuffer = Buffer.from(keyBase64, 'base64');\n return await crypto.subtle.importKey(\n 'raw',\n keyBuffer,\n {\n name: 'Ed25519',\n namedCurve: 'Ed25519',\n },\n true,\n ['verify']\n );\n }\n\n /**\n * Verify signature\n */\n private async verifySignature(\n registryJson: string,\n signature: RegistrySignature,\n publicKey: CryptoKey\n ): Promise<boolean> {\n if (signature.algorithm !== 'ed25519') {\n return false;\n }\n\n const data = new TextEncoder().encode(registryJson);\n const sigBuffer = Buffer.from(signature.signature, 'base64');\n return await crypto.subtle.verify('Ed25519', publicKey, sigBuffer, data);\n }\n\n /**\n * Verify registry signature\n */\n private async verifyRegistrySignature(\n registryJson: string,\n signature: RegistrySignature\n ): Promise<boolean> {\n if (this.publicKeys.length === 0) {\n // No public keys configured - skip verification (dev mode)\n return true;\n }\n\n // Try each public key\n for (const pubkeyBase64 of this.publicKeys) {\n try {\n const publicKey = await this.importPublicKey(pubkeyBase64);\n const isValid = await this.verifySignature(registryJson, signature, publicKey);\n if (isValid) {\n return true;\n }\n } catch {\n // Try next key\n continue;\n }\n }\n\n return false;\n }\n\n /**\n * Fetch registry and signature from network\n */\n private async fetchFromNetwork(): Promise<{\n registry: WalletRegistryV1;\n signature: RegistrySignature;\n etag?: string;\n }> {\n const registryUrl = this.getRegistryUrl();\n const sigUrl = this.getSignatureUrl();\n const requireSignature = this.publicKeys.length > 0;\n\n // AbortController for fetch timeout\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.fetchTimeout);\n\n try {\n // Fetch registry (always required)\n const registryResponse = await this.fetchFn(registryUrl, {\n headers: {\n 'Accept': 'application/json',\n 'If-None-Match': this.memoryCache.lastKnownGood?.etag || '',\n },\n signal: controller.signal,\n });\n\n // Handle 304 Not Modified\n if (registryResponse.status === 304) {\n if (this.memoryCache.lastKnownGood) {\n // For 304, we still need a signature object for return type\n // In dev mode, create dummy signature (skip fetch entirely)\n let signature: RegistrySignature;\n if (requireSignature) {\n // Production mode: try to fetch signature\n try {\n const sigResponse = await this.fetchFn(sigUrl, {\n headers: { 'Accept': 'application/json' },\n signal: controller.signal,\n });\n if (sigResponse.ok) {\n signature = JSON.parse(await sigResponse.text()) as RegistrySignature;\n } else {\n // Signature missing but we have cache - use dummy\n signature = { algorithm: 'ed25519', signature: '', keyFingerprint: '', signedAt: new Date().toISOString() };\n }\n } catch {\n signature = { algorithm: 'ed25519', signature: '', keyFingerprint: '', signedAt: new Date().toISOString() };\n }\n } else {\n // Dev mode: create dummy signature\n signature = { algorithm: 'ed25519', signature: '', keyFingerprint: '', signedAt: new Date().toISOString() };\n }\n \n return {\n registry: this.memoryCache.lastKnownGood.registry,\n signature,\n etag: this.memoryCache.lastKnownGood.etag,\n };\n }\n }\n\n if (!registryResponse.ok) {\n throw new RegistryFetchFailedError(\n registryUrl,\n new Error(`${registryResponse.status} ${registryResponse.statusText}`)\n );\n }\n\n const registryJson = await registryResponse.text();\n const registry = JSON.parse(registryJson) as WalletRegistryV1;\n const etag = registryResponse.headers.get('ETag') || undefined;\n\n // Validate schema\n if (!validateRegistry(registry)) {\n throw new RegistrySchemaInvalidError(\n 'Invalid registry schema',\n { url: registryUrl }\n );\n }\n\n // Fetch signature (skip entirely in dev mode when no public keys)\n let signature: RegistrySignature;\n \n if (requireSignature) {\n // Public keys configured - signature is required\n const sigResponse = await this.fetchFn(sigUrl, {\n headers: {\n 'Accept': 'application/json',\n },\n signal: controller.signal,\n });\n\n if (!sigResponse.ok) {\n throw new RegistryFetchFailedError(\n sigUrl,\n new Error(`${sigResponse.status} ${sigResponse.statusText}`)\n );\n }\n signature = JSON.parse(await sigResponse.text()) as RegistrySignature;\n \n // Verify signature\n const verified = await this.verifyRegistrySignature(registryJson, signature);\n if (!verified) {\n throw new RegistryVerificationFailedError(\n 'Signature verification failed',\n { url: registryUrl }\n );\n }\n } else {\n // Dev mode: skip signature fetch entirely, create dummy signature\n console.log('[RegistryClient] Dev mode: skipping signature fetch (no public keys configured)');\n signature = { algorithm: 'ed25519', signature: '', keyFingerprint: '', signedAt: new Date().toISOString() };\n }\n\n // Check sequence number (prevent downgrades)\n if (this.memoryCache.lastKnownGood) {\n if (registry.metadata.sequence < this.memoryCache.lastKnownGood.sequence) {\n throw new RegistryVerificationFailedError(\n `Sequence downgrade detected: ${registry.metadata.sequence} < ${this.memoryCache.lastKnownGood.sequence}`,\n { url: registryUrl }\n );\n }\n }\n\n return { registry, signature, etag };\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n /**\n * Get registry with SWR pattern\n * - Returns cached immediately if available\n * - Refreshes in background\n */\n async getRegistry(): Promise<WalletRegistryV1> {\n // Return cached immediately if available\n if (this.memoryCache.lastKnownGood) {\n const now = Date.now();\n const age = now - this.memoryCache.lastKnownGood.fetchedAt;\n\n // If cache is fresh, return it\n if (age < this.cacheTtl) {\n // Trigger background refresh if not already refreshing\n if (!this.memoryCache.refreshPromise) {\n this.memoryCache.refreshPromise = this.refreshRegistry();\n }\n return this.memoryCache.lastKnownGood.registry;\n }\n\n // Cache is stale but usable\n if (age < this.staleTtl) {\n // Trigger refresh\n if (!this.memoryCache.refreshPromise) {\n this.memoryCache.refreshPromise = this.refreshRegistry();\n }\n return this.memoryCache.lastKnownGood.registry;\n }\n }\n\n // No cache or too stale - fetch synchronously\n return await this.refreshRegistry();\n }\n\n /**\n * Refresh registry from network\n */\n private async refreshRegistry(): Promise<WalletRegistryV1> {\n // If already refreshing, wait for that\n if (this.memoryCache.refreshPromise) {\n return await this.memoryCache.refreshPromise;\n }\n\n const refreshPromise = (async () => {\n try {\n const { registry, etag } = await this.fetchFromNetwork();\n\n console.log('[RegistryClient] Successfully fetched registry:', {\n channel: registry.metadata.channel,\n sequence: registry.metadata.sequence,\n walletCount: registry.wallets.length,\n });\n\n // Update cache\n const cached: CachedRegistry = {\n registry,\n verified: true,\n fetchedAt: Date.now(),\n etag,\n sequence: registry.metadata.sequence,\n };\n\n this.memoryCache.lastKnownGood = cached;\n this.memoryCache.lastAttempt = {\n fetchedAt: Date.now(),\n };\n\n // Update status\n this.updateStatus({\n source: 'network',\n verified: true,\n channel: registry.metadata.channel,\n sequence: registry.metadata.sequence,\n stale: false,\n fetchedAt: cached.fetchedAt,\n etag,\n });\n\n // Persist to storage\n if (this.storage) {\n await this.saveToStorage(cached);\n }\n\n return registry;\n } catch (error) {\n // Update last attempt\n this.memoryCache.lastAttempt = {\n fetchedAt: Date.now(),\n errorCode:\n error instanceof RegistryFetchFailedError\n ? 'REGISTRY_FETCH_FAILED'\n : error instanceof RegistryVerificationFailedError\n ? 'REGISTRY_VERIFICATION_FAILED'\n : error instanceof RegistrySchemaInvalidError\n ? 'REGISTRY_SCHEMA_INVALID'\n : 'UNKNOWN',\n };\n\n // Update status with error\n const lastKnownGood = this.memoryCache.lastKnownGood;\n if (lastKnownGood) {\n const cantonError = error instanceof RegistryFetchFailedError ||\n error instanceof RegistryVerificationFailedError ||\n error instanceof RegistrySchemaInvalidError\n ? error\n : undefined;\n this.updateStatus({\n source: 'cache',\n verified: lastKnownGood.verified,\n channel: lastKnownGood.registry.metadata.channel,\n sequence: lastKnownGood.sequence,\n stale: Date.now() - lastKnownGood.fetchedAt > this.cacheTtl,\n fetchedAt: lastKnownGood.fetchedAt,\n etag: lastKnownGood.etag,\n error: cantonError,\n });\n\n // Return last known good\n return lastKnownGood.registry;\n }\n\n // No cache available - rethrow\n throw error;\n } finally {\n this.memoryCache.refreshPromise = null;\n }\n })();\n\n this.memoryCache.refreshPromise = refreshPromise;\n return await refreshPromise;\n }\n\n /**\n * Update registry status\n */\n private updateStatus(status: RegistryStatus): void {\n this.currentStatus = status;\n }\n\n /**\n * Get current registry status\n */\n getStatus(): RegistryStatus | null {\n if (!this.memoryCache.lastKnownGood) {\n return null;\n }\n\n const now = Date.now();\n const age = now - this.memoryCache.lastKnownGood.fetchedAt;\n\n return {\n source: this.currentStatus?.source || 'cache',\n verified: this.memoryCache.lastKnownGood.verified,\n channel: this.memoryCache.lastKnownGood.registry.metadata.channel,\n sequence: this.memoryCache.lastKnownGood.sequence,\n stale: age > this.cacheTtl,\n fetchedAt: this.memoryCache.lastKnownGood.fetchedAt,\n etag: this.memoryCache.lastKnownGood.etag,\n error: this.currentStatus?.error,\n };\n }\n\n /**\n * Save to persistent storage\n */\n private async saveToStorage(cached: CachedRegistry): Promise<void> {\n if (!this.storage) return;\n\n const key = `registry_${this.channel}`;\n const value = JSON.stringify(cached);\n await this.storage.set(key, value);\n }\n\n /**\n * Load from persistent storage\n */\n private async loadFromStorage(): Promise<void> {\n if (!this.storage) return;\n\n const key = `registry_${this.channel}`;\n const value = await this.storage.get(key);\n if (value) {\n try {\n const cached = JSON.parse(value) as CachedRegistry;\n this.memoryCache.lastKnownGood = cached;\n } catch {\n // Ignore parse errors\n }\n }\n }\n\n /**\n * Get all wallets\n */\n async getWallets(): Promise<WalletInfo[]> {\n const registry = await this.getRegistry();\n return registry.wallets.map((entry) =>\n registryEntryToWalletInfo(entry, registry.metadata.channel)\n );\n }\n\n /**\n * Get wallet by ID\n */\n async getWallet(walletId: string): Promise<WalletInfo> {\n const registry = await this.getRegistry();\n const entry = registry.wallets.find((w) => w.id === walletId);\n\n if (!entry) {\n throw new WalletNotFoundError(walletId);\n }\n\n return registryEntryToWalletInfo(entry, registry.metadata.channel);\n }\n\n /**\n * Get wallet entry (includes adapter config)\n */\n async getWalletEntry(walletId: string): Promise<RegistryWalletEntry> {\n const registry = await this.getRegistry();\n const entry = registry.wallets.find((w) => w.id === walletId);\n\n if (!entry) {\n throw new WalletNotFoundError(walletId);\n }\n\n if (!validateWalletEntry(entry)) {\n throw new RegistrySchemaInvalidError(\n `Invalid wallet entry for ${walletId}`,\n { url: this.getRegistryUrl() }\n );\n }\n\n return entry;\n }\n\n /**\n * Clear cache\n */\n clearCache(): void {\n this.memoryCache.lastKnownGood = null;\n this.memoryCache.lastAttempt = null;\n this.memoryCache.refreshPromise = null;\n this.currentStatus = null;\n\n if (this.storage) {\n this.storage.remove(`registry_${this.channel}`).catch(() => {\n // Ignore errors\n });\n }\n }\n\n /**\n * Check if cache is valid\n */\n isCacheValid(): boolean {\n if (!this.enableCache || !this.memoryCache.lastKnownGood) {\n return false;\n }\n\n const now = Date.now();\n return now - this.memoryCache.lastKnownGood.fetchedAt < this.cacheTtl;\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@partylayer/registry-client",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"description": "Wallet registry client for PartyLayer",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -24,15 +24,15 @@
|
|
|
24
24
|
"license": "MIT",
|
|
25
25
|
"repository": {
|
|
26
26
|
"type": "git",
|
|
27
|
-
"url": "https://github.com/
|
|
27
|
+
"url": "https://github.com/PartyLayer/PartyLayer.git",
|
|
28
28
|
"directory": "packages/registry-client"
|
|
29
29
|
},
|
|
30
|
-
"homepage": "https://github.com/
|
|
30
|
+
"homepage": "https://github.com/PartyLayer/PartyLayer#readme",
|
|
31
31
|
"bugs": {
|
|
32
|
-
"url": "https://github.com/
|
|
32
|
+
"url": "https://github.com/PartyLayer/PartyLayer/issues"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@partylayer/core": "0.2.
|
|
35
|
+
"@partylayer/core": "0.2.4"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@types/node": "^20.11.0",
|