@partylayer/registry-client 0.2.7 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +27 -2
- package/dist/index.d.ts +27 -2
- package/dist/index.js +36 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +17 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { NetworkId, WalletInfo, PartyLayerError } from '@partylayer/core';
|
|
2
|
-
export { WalletInfo } from '@partylayer/core';
|
|
1
|
+
import { NetworkId, ProviderDetection, Cip0103Support, WalletInfo, PartyLayerError } from '@partylayer/core';
|
|
2
|
+
export { Cip0103StatusForDetection, Cip0103Support, ProviderDetection, ProviderMatcher, WalletInfo, deriveGenericWalletName, findMatchingWallet, findMatchingWalletInfo, isCip0103Native, matchesProviderDetection } from '@partylayer/core';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Wallet Registry Schema v1
|
|
@@ -77,6 +77,31 @@ interface RegistryWalletEntry {
|
|
|
77
77
|
version?: string;
|
|
78
78
|
/** Origin allowlist (optional - if present, only these origins can connect) */
|
|
79
79
|
originAllowlist?: string[];
|
|
80
|
+
/**
|
|
81
|
+
* Marks the entry as beta even when it ships in the `stable` registry
|
|
82
|
+
* channel. UIs (modal, picker, capability matrix) can use this flag to
|
|
83
|
+
* surface a "Beta" badge regardless of which channel file the entry
|
|
84
|
+
* lives in. Optional and additive — older registries omit it and the
|
|
85
|
+
* flag defaults to `false`.
|
|
86
|
+
*/
|
|
87
|
+
beta?: boolean;
|
|
88
|
+
/**
|
|
89
|
+
* Optional CIP-0103 runtime detection rules. When present, the SDK +
|
|
90
|
+
* picker can match the currently-injected `window.canton` provider to
|
|
91
|
+
* this entry and surface it in the "CIP-0103 Native" section with full
|
|
92
|
+
* branding. Lets us add new CIP-0103 wallets to the ecosystem with a
|
|
93
|
+
* registry JSON update — no SDK code change required.
|
|
94
|
+
*/
|
|
95
|
+
providerDetection?: ProviderDetection;
|
|
96
|
+
/**
|
|
97
|
+
* Canonical CIP-0103 support marker. When `cip0103.native === true`
|
|
98
|
+
* the picker always renders this entry in the "CIP-0103 NATIVE"
|
|
99
|
+
* section, regardless of install state. The accompanying `evidence`
|
|
100
|
+
* field is intended to be a public URL that justifies the claim
|
|
101
|
+
* (npm package readme, blog post, etc.) and may be surfaced by UIs as
|
|
102
|
+
* a tooltip / "verified" link.
|
|
103
|
+
*/
|
|
104
|
+
cip0103?: Cip0103Support;
|
|
80
105
|
}
|
|
81
106
|
/**
|
|
82
107
|
* Registry metadata
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { NetworkId, WalletInfo, PartyLayerError } from '@partylayer/core';
|
|
2
|
-
export { WalletInfo } from '@partylayer/core';
|
|
1
|
+
import { NetworkId, ProviderDetection, Cip0103Support, WalletInfo, PartyLayerError } from '@partylayer/core';
|
|
2
|
+
export { Cip0103StatusForDetection, Cip0103Support, ProviderDetection, ProviderMatcher, WalletInfo, deriveGenericWalletName, findMatchingWallet, findMatchingWalletInfo, isCip0103Native, matchesProviderDetection } from '@partylayer/core';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Wallet Registry Schema v1
|
|
@@ -77,6 +77,31 @@ interface RegistryWalletEntry {
|
|
|
77
77
|
version?: string;
|
|
78
78
|
/** Origin allowlist (optional - if present, only these origins can connect) */
|
|
79
79
|
originAllowlist?: string[];
|
|
80
|
+
/**
|
|
81
|
+
* Marks the entry as beta even when it ships in the `stable` registry
|
|
82
|
+
* channel. UIs (modal, picker, capability matrix) can use this flag to
|
|
83
|
+
* surface a "Beta" badge regardless of which channel file the entry
|
|
84
|
+
* lives in. Optional and additive — older registries omit it and the
|
|
85
|
+
* flag defaults to `false`.
|
|
86
|
+
*/
|
|
87
|
+
beta?: boolean;
|
|
88
|
+
/**
|
|
89
|
+
* Optional CIP-0103 runtime detection rules. When present, the SDK +
|
|
90
|
+
* picker can match the currently-injected `window.canton` provider to
|
|
91
|
+
* this entry and surface it in the "CIP-0103 Native" section with full
|
|
92
|
+
* branding. Lets us add new CIP-0103 wallets to the ecosystem with a
|
|
93
|
+
* registry JSON update — no SDK code change required.
|
|
94
|
+
*/
|
|
95
|
+
providerDetection?: ProviderDetection;
|
|
96
|
+
/**
|
|
97
|
+
* Canonical CIP-0103 support marker. When `cip0103.native === true`
|
|
98
|
+
* the picker always renders this entry in the "CIP-0103 NATIVE"
|
|
99
|
+
* section, regardless of install state. The accompanying `evidence`
|
|
100
|
+
* field is intended to be a public URL that justifies the claim
|
|
101
|
+
* (npm package readme, blog post, etc.) and may be surfaced by UIs as
|
|
102
|
+
* a tooltip / "verified" link.
|
|
103
|
+
*/
|
|
104
|
+
cip0103?: Cip0103Support;
|
|
80
105
|
}
|
|
81
106
|
/**
|
|
82
107
|
* Registry metadata
|
package/dist/index.js
CHANGED
|
@@ -86,8 +86,22 @@ function registryEntryToWalletInfo(entry, channel) {
|
|
|
86
86
|
minSdkVersion: entry.sdkVersion,
|
|
87
87
|
networks: entry.supportedNetworks,
|
|
88
88
|
channel,
|
|
89
|
-
//
|
|
90
|
-
|
|
89
|
+
// Adapter metadata is exposed to the picker via WalletInfo.metadata
|
|
90
|
+
// (typed `Record<string, string>`). Two flags routed through here today:
|
|
91
|
+
// - originAllowlist: SDK-side origin enforcement
|
|
92
|
+
// - beta: UI badge ("Beta" tag in modal + capability matrix)
|
|
93
|
+
// Both are optional — only emitted when the registry entry sets them.
|
|
94
|
+
...entry.originAllowlist || entry.beta ? {
|
|
95
|
+
metadata: {
|
|
96
|
+
...entry.originAllowlist ? { originAllowlist: JSON.stringify(entry.originAllowlist) } : {},
|
|
97
|
+
...entry.beta ? { beta: "true" } : {}
|
|
98
|
+
}
|
|
99
|
+
} : {},
|
|
100
|
+
// CIP-0103 runtime-detection rules pass through verbatim when present;
|
|
101
|
+
// see WalletInfo.providerDetection for how the picker uses them.
|
|
102
|
+
...entry.providerDetection ? { providerDetection: entry.providerDetection } : {},
|
|
103
|
+
// Canonical CIP-0103 support marker.
|
|
104
|
+
...entry.cip0103 ? { cip0103: entry.cip0103 } : {}
|
|
91
105
|
};
|
|
92
106
|
}
|
|
93
107
|
function registryEntryToMetadata(entry) {
|
|
@@ -489,6 +503,26 @@ var RegistryClient = class {
|
|
|
489
503
|
}
|
|
490
504
|
};
|
|
491
505
|
|
|
506
|
+
Object.defineProperty(exports, "deriveGenericWalletName", {
|
|
507
|
+
enumerable: true,
|
|
508
|
+
get: function () { return core.deriveGenericWalletName; }
|
|
509
|
+
});
|
|
510
|
+
Object.defineProperty(exports, "findMatchingWallet", {
|
|
511
|
+
enumerable: true,
|
|
512
|
+
get: function () { return core.findMatchingWallet; }
|
|
513
|
+
});
|
|
514
|
+
Object.defineProperty(exports, "findMatchingWalletInfo", {
|
|
515
|
+
enumerable: true,
|
|
516
|
+
get: function () { return core.findMatchingWalletInfo; }
|
|
517
|
+
});
|
|
518
|
+
Object.defineProperty(exports, "isCip0103Native", {
|
|
519
|
+
enumerable: true,
|
|
520
|
+
get: function () { return core.isCip0103Native; }
|
|
521
|
+
});
|
|
522
|
+
Object.defineProperty(exports, "matchesProviderDetection", {
|
|
523
|
+
enumerable: true,
|
|
524
|
+
get: function () { return core.matchesProviderDetection; }
|
|
525
|
+
});
|
|
492
526
|
exports.REGISTRY_SCHEMA_VERSION = REGISTRY_SCHEMA_VERSION;
|
|
493
527
|
exports.RegistryClient = RegistryClient;
|
|
494
528
|
exports.registryEntryToMetadata = registryEntryToMetadata;
|
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 mobileConnect?: boolean;\n remoteSigner?: 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 /** Deep link URL for mobile wallet connect */\n deeplink?: string;\n /** OAuth-based authentication */\n oauth?: boolean;\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 // Transport capabilities — inferred from installation hints and capability flags\n if (entry.installation?.windowProperty) {\n capabilities.push('injected');\n }\n if (entry.installation?.deeplink || entry.capabilities.mobileConnect) {\n capabilities.push('deeplink');\n }\n if (entry.capabilities.remoteSigner) {\n capabilities.push('remoteSigner');\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 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 // 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":"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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 {\n CapabilityKey,\n Cip0103Support,\n NetworkId,\n ProviderDetection,\n WalletInfo,\n} 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 mobileConnect?: boolean;\n remoteSigner?: 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 /** Deep link URL for mobile wallet connect */\n deeplink?: string;\n /** OAuth-based authentication */\n oauth?: boolean;\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 * Marks the entry as beta even when it ships in the `stable` registry\n * channel. UIs (modal, picker, capability matrix) can use this flag to\n * surface a \"Beta\" badge regardless of which channel file the entry\n * lives in. Optional and additive — older registries omit it and the\n * flag defaults to `false`.\n */\n beta?: boolean;\n /**\n * Optional CIP-0103 runtime detection rules. When present, the SDK +\n * picker can match the currently-injected `window.canton` provider to\n * this entry and surface it in the \"CIP-0103 Native\" section with full\n * branding. Lets us add new CIP-0103 wallets to the ecosystem with a\n * registry JSON update — no SDK code change required.\n */\n providerDetection?: ProviderDetection;\n /**\n * Canonical CIP-0103 support marker. When `cip0103.native === true`\n * the picker always renders this entry in the \"CIP-0103 NATIVE\"\n * section, regardless of install state. The accompanying `evidence`\n * field is intended to be a public URL that justifies the claim\n * (npm package readme, blog post, etc.) and may be surfaced by UIs as\n * a tooltip / \"verified\" link.\n */\n cip0103?: Cip0103Support;\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 // Transport capabilities — inferred from installation hints and capability flags\n if (entry.installation?.windowProperty) {\n capabilities.push('injected');\n }\n if (entry.installation?.deeplink || entry.capabilities.mobileConnect) {\n capabilities.push('deeplink');\n }\n if (entry.capabilities.remoteSigner) {\n capabilities.push('remoteSigner');\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 // Adapter metadata is exposed to the picker via WalletInfo.metadata\n // (typed `Record<string, string>`). Two flags routed through here today:\n // - originAllowlist: SDK-side origin enforcement\n // - beta: UI badge (\"Beta\" tag in modal + capability matrix)\n // Both are optional — only emitted when the registry entry sets them.\n ...((entry.originAllowlist || entry.beta)\n ? {\n metadata: {\n ...(entry.originAllowlist\n ? { originAllowlist: JSON.stringify(entry.originAllowlist) }\n : {}),\n ...(entry.beta ? { beta: 'true' } : {}),\n },\n }\n : {}),\n // CIP-0103 runtime-detection rules pass through verbatim when present;\n // see WalletInfo.providerDetection for how the picker uses them.\n ...(entry.providerDetection ? { providerDetection: entry.providerDetection } : {}),\n // Canonical CIP-0103 support marker.\n ...(entry.cip0103 ? { cip0103: entry.cip0103 } : {}),\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 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 // 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
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { toWalletId, RegistryFetchFailedError, RegistrySchemaInvalidError, RegistryVerificationFailedError, WalletNotFoundError } from '@partylayer/core';
|
|
2
|
+
export { deriveGenericWalletName, findMatchingWallet, findMatchingWalletInfo, isCip0103Native, matchesProviderDetection } from '@partylayer/core';
|
|
2
3
|
|
|
3
4
|
// src/schema.ts
|
|
4
5
|
var REGISTRY_SCHEMA_VERSION = "1.0.0";
|
|
@@ -84,8 +85,22 @@ function registryEntryToWalletInfo(entry, channel) {
|
|
|
84
85
|
minSdkVersion: entry.sdkVersion,
|
|
85
86
|
networks: entry.supportedNetworks,
|
|
86
87
|
channel,
|
|
87
|
-
//
|
|
88
|
-
|
|
88
|
+
// Adapter metadata is exposed to the picker via WalletInfo.metadata
|
|
89
|
+
// (typed `Record<string, string>`). Two flags routed through here today:
|
|
90
|
+
// - originAllowlist: SDK-side origin enforcement
|
|
91
|
+
// - beta: UI badge ("Beta" tag in modal + capability matrix)
|
|
92
|
+
// Both are optional — only emitted when the registry entry sets them.
|
|
93
|
+
...entry.originAllowlist || entry.beta ? {
|
|
94
|
+
metadata: {
|
|
95
|
+
...entry.originAllowlist ? { originAllowlist: JSON.stringify(entry.originAllowlist) } : {},
|
|
96
|
+
...entry.beta ? { beta: "true" } : {}
|
|
97
|
+
}
|
|
98
|
+
} : {},
|
|
99
|
+
// CIP-0103 runtime-detection rules pass through verbatim when present;
|
|
100
|
+
// see WalletInfo.providerDetection for how the picker uses them.
|
|
101
|
+
...entry.providerDetection ? { providerDetection: entry.providerDetection } : {},
|
|
102
|
+
// Canonical CIP-0103 support marker.
|
|
103
|
+
...entry.cip0103 ? { cip0103: entry.cip0103 } : {}
|
|
89
104
|
};
|
|
90
105
|
}
|
|
91
106
|
function registryEntryToMetadata(entry) {
|
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 mobileConnect?: boolean;\n remoteSigner?: 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 /** Deep link URL for mobile wallet connect */\n deeplink?: string;\n /** OAuth-based authentication */\n oauth?: boolean;\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 // Transport capabilities — inferred from installation hints and capability flags\n if (entry.installation?.windowProperty) {\n capabilities.push('injected');\n }\n if (entry.installation?.deeplink || entry.capabilities.mobileConnect) {\n capabilities.push('deeplink');\n }\n if (entry.capabilities.remoteSigner) {\n capabilities.push('remoteSigner');\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 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 // 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 {\n CapabilityKey,\n Cip0103Support,\n NetworkId,\n ProviderDetection,\n WalletInfo,\n} 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 mobileConnect?: boolean;\n remoteSigner?: 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 /** Deep link URL for mobile wallet connect */\n deeplink?: string;\n /** OAuth-based authentication */\n oauth?: boolean;\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 * Marks the entry as beta even when it ships in the `stable` registry\n * channel. UIs (modal, picker, capability matrix) can use this flag to\n * surface a \"Beta\" badge regardless of which channel file the entry\n * lives in. Optional and additive — older registries omit it and the\n * flag defaults to `false`.\n */\n beta?: boolean;\n /**\n * Optional CIP-0103 runtime detection rules. When present, the SDK +\n * picker can match the currently-injected `window.canton` provider to\n * this entry and surface it in the \"CIP-0103 Native\" section with full\n * branding. Lets us add new CIP-0103 wallets to the ecosystem with a\n * registry JSON update — no SDK code change required.\n */\n providerDetection?: ProviderDetection;\n /**\n * Canonical CIP-0103 support marker. When `cip0103.native === true`\n * the picker always renders this entry in the \"CIP-0103 NATIVE\"\n * section, regardless of install state. The accompanying `evidence`\n * field is intended to be a public URL that justifies the claim\n * (npm package readme, blog post, etc.) and may be surfaced by UIs as\n * a tooltip / \"verified\" link.\n */\n cip0103?: Cip0103Support;\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 // Transport capabilities — inferred from installation hints and capability flags\n if (entry.installation?.windowProperty) {\n capabilities.push('injected');\n }\n if (entry.installation?.deeplink || entry.capabilities.mobileConnect) {\n capabilities.push('deeplink');\n }\n if (entry.capabilities.remoteSigner) {\n capabilities.push('remoteSigner');\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 // Adapter metadata is exposed to the picker via WalletInfo.metadata\n // (typed `Record<string, string>`). Two flags routed through here today:\n // - originAllowlist: SDK-side origin enforcement\n // - beta: UI badge (\"Beta\" tag in modal + capability matrix)\n // Both are optional — only emitted when the registry entry sets them.\n ...((entry.originAllowlist || entry.beta)\n ? {\n metadata: {\n ...(entry.originAllowlist\n ? { originAllowlist: JSON.stringify(entry.originAllowlist) }\n : {}),\n ...(entry.beta ? { beta: 'true' } : {}),\n },\n }\n : {}),\n // CIP-0103 runtime-detection rules pass through verbatim when present;\n // see WalletInfo.providerDetection for how the picker uses them.\n ...(entry.providerDetection ? { providerDetection: entry.providerDetection } : {}),\n // Canonical CIP-0103 support marker.\n ...(entry.cip0103 ? { cip0103: entry.cip0103 } : {}),\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 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 // 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.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Wallet registry client for PartyLayer",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"url": "https://github.com/PartyLayer/PartyLayer/issues"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@partylayer/core": "0.2.7"
|
|
35
|
+
"@partylayer/core": "^0.2.7"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@types/node": "^20.11.0",
|