@lukso/transaction-view-headless 0.4.9 → 0.5.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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/config/lukso-config.ts","../src/hooks/useAddressResolution.ts","../src/index.ts","../src/composables/index.ts","../src/composables/use-image-loader.ts","../src/utils/view-matcher.ts","../src/registry/view-registry.ts","../src/composables/use-transaction-playback.ts","../src/composables/use-transaction-view.ts","../src/registry/view-loader.ts","../src/hooks/useAddressQuery.ts","../src/types/view-events.ts"],"sourcesContent":["/**\n * Framework-agnostic LUKSO configuration system\n * Works across Vue, React, and Lit components\n */\n\nimport { signal } from '@preact/signals-core'\nimport type { Chain } from 'viem'\n\nexport interface LuksoConfig {\n /** Chain ID for LUKSO network (42 for mainnet, 4201 for testnet) */\n chainId: number\n /** RPC endpoint for the LUKSO network */\n rpcUrl: string\n /** GraphQL endpoint for address resolution */\n graphqlEndpoint?: string\n /** IPFS gateway for profile images and metadata */\n ipfsGateway?: string\n /** Enable/disable address resolution */\n enableAddressResolution?: boolean\n /** Cache duration for resolved addresses (in milliseconds) */\n cacheDuration?: number\n}\n\nconst DEFAULT_CONFIG: LuksoConfig = {\n chainId: 42, // LUKSO mainnet\n rpcUrl: 'https://rpc.lukso.network',\n graphqlEndpoint: '/api/graphql', // Use local API proxy\n ipfsGateway: 'https://api.universalprofile.cloud/ipfs',\n enableAddressResolution: true,\n cacheDuration: 5 * 60 * 1000, // 5 minutes\n}\n\nlet globalConfig: LuksoConfig = { ...DEFAULT_CONFIG }\n\n/**\n * Set global LUKSO configuration\n * Call this once to configure all transaction components\n */\nexport function setLuksoConfig(config: Partial<LuksoConfig>): void {\n globalConfig = { ...globalConfig, ...config }\n\n // Clear any existing address resolution cache when config changes\n clearAddressCache()\n\n if (typeof window !== 'undefined' && window.console) {\n console.log('🌐 LUKSO Config Updated:', {\n chainId: globalConfig.chainId,\n network:\n globalConfig.chainId === 42\n ? 'mainnet'\n : globalConfig.chainId === 4201\n ? 'testnet'\n : 'custom',\n addressResolution: globalConfig.enableAddressResolution,\n })\n }\n}\n\n/**\n * Get current LUKSO configuration\n */\nexport function getLuksoConfig(): LuksoConfig {\n return { ...globalConfig }\n}\n\n/**\n * Quick helper to set mainnet configuration\n */\nexport function useLuksoMainnet(): void {\n setLuksoConfig({\n chainId: 42,\n rpcUrl: 'https://rpc.lukso.network',\n })\n}\n\n/**\n * Quick helper to set testnet configuration\n */\nexport function useLuksoTestnet(): void {\n setLuksoConfig({\n chainId: 4201,\n rpcUrl: 'https://rpc.testnet.lukso.network',\n })\n}\n\n/**\n * Address resolution cache\n */\nconst addressCache = new Map<string, any>()\nconst cacheTimestamps = new Map<string, number>()\n\nexport function cacheAddress(address: string, data: any): void {\n if (!globalConfig.enableAddressResolution) return\n\n const key = address.toLowerCase()\n addressCache.set(key, data)\n cacheTimestamps.set(key, Date.now())\n}\n\nexport function getCachedAddress(address: string): any | null {\n if (!globalConfig.enableAddressResolution) return null\n\n const key = address.toLowerCase()\n const data = addressCache.get(key)\n const timestamp = cacheTimestamps.get(key)\n\n if (!data || !timestamp) return null\n\n // Check if cache is expired\n if (\n typeof globalConfig.cacheDuration === 'number' &&\n Date.now() - timestamp > globalConfig.cacheDuration\n ) {\n addressCache.delete(key)\n cacheTimestamps.delete(key)\n return null\n }\n\n return data\n}\n\nexport function clearAddressCache(): void {\n addressCache.clear()\n cacheTimestamps.clear()\n}\n\n/**\n * Check if address resolution is enabled\n */\nexport function isAddressResolutionEnabled(): boolean {\n return globalConfig.enableAddressResolution ?? true\n}\n\n/**\n * Current chain signal for reactive chain state\n */\nexport const currentChainSignal = signal<Chain | null>(null)\n\n/**\n * Set current chain signal from viem chain object\n */\nexport function setCurrentChain(chain: Chain): void {\n currentChainSignal.value = chain\n\n // Also update the legacy global config for backwards compatibility\n setLuksoConfig({\n chainId: chain.id,\n rpcUrl: chain.rpcUrls.default.http[0],\n })\n}\n\n/**\n * Get current chain, falling back to chain derived from global config\n */\nexport function getCurrentChain(): Chain | null {\n return currentChainSignal.value\n}\n\n/**\n * Initialize chain signal from global config\n */\nexport async function initializeChainSignal(): Promise<void> {\n if (currentChainSignal.value) return\n\n try {\n const { lukso, luksoTestnet } = await import('viem/chains')\n const config = getLuksoConfig()\n\n const chain = config.chainId === 42 ? lukso : luksoTestnet\n currentChainSignal.value = chain\n } catch (error) {\n console.warn('Failed to initialize chain signal:', error)\n }\n}\n","/**\n * Framework-agnostic address resolution hook\n * Can be adapted for Vue (composable), React (hook), or Lit (controller)\n * Uses batching mechanism inspired by the decoder package\n */\n\nimport type {\n AssetData,\n EnhancedInfo,\n ProfileData,\n TokenData,\n} from '@lukso/transaction-decoder'\nimport {\n cacheAddress,\n currentChainSignal,\n getCachedAddress,\n getLuksoConfig,\n initializeChainSignal,\n isAddressResolutionEnabled,\n} from '../config/lukso-config'\n\n/**\n * Union type of all possible resolved address data\n * Combines Profile, Asset, and Token data structures\n */\nexport type ResolvedAddress = {\n address: string\n hasProfile: boolean\n truncatedAddress: string\n __gqltype?: 'Profile' | 'Asset' | 'Token' | 'Contract'\n} & Partial<ProfileData> &\n Partial<AssetData> &\n Partial<TokenData>\n\n/**\n * Truncate address to 0x{first5}...{last4} format\n */\nfunction truncateAddress(\n address: string,\n prefixLength = 5,\n suffixLength = 4\n): string {\n if (!address || address.length <= prefixLength + suffixLength + 2) {\n return address\n }\n\n const prefix = address.slice(0, 2 + prefixLength) // 0x + first 5\n const suffix = address.slice(-suffixLength) // last 4\n\n return `${prefix}...${suffix}`\n}\n\n// Per-chain batching state\ninterface ChainBatchState {\n batchTimeout: NodeJS.Timeout | null\n batchQueue: Set<string>\n batchResolvers: Map<string, (result: ResolvedAddress) => void>\n pendingResolutions: Map<string, Promise<ResolvedAddress>>\n isProcessing: boolean // Prevent concurrent batch processing\n}\n\nconst chainBatchStates = new Map<number, ChainBatchState>()\nconst BATCH_DELAY = 0 // Just wait for next tick to batch addresses from the same render cycle\nconst BATCH_SIZE = 50\n\n/**\n * Get or create batch state for a specific chain\n */\nfunction getBatchState(chainId: number): ChainBatchState {\n let state = chainBatchStates.get(chainId)\n if (!state) {\n state = {\n batchTimeout: null,\n batchQueue: new Set<string>(),\n batchResolvers: new Map<string, (result: ResolvedAddress) => void>(),\n pendingResolutions: new Map<string, Promise<ResolvedAddress>>(),\n isProcessing: false,\n }\n chainBatchStates.set(chainId, state)\n }\n return state\n}\n\n/**\n * Process a batch of addresses using decoder package's GraphQL resolver\n */\nasync function processBatch(chainId: number): Promise<void> {\n const state = getBatchState(chainId)\n if (state.batchQueue.size === 0 || state.isProcessing) return\n\n // Prevent concurrent processing for this chain\n state.isProcessing = true\n\n const addresses = Array.from(state.batchQueue)\n state.batchQueue.clear()\n\n try {\n // Use decoder package's GraphQL resolver\n const { fetchMultipleAddresses, getGraphQLEndpoint } = await import(\n '@lukso/transaction-decoder'\n )\n const { lukso, luksoTestnet } = await import('viem/chains')\n\n // Get the appropriate chain\n const chain = chainId === 42 ? lukso : luksoTestnet\n const graphqlEndpoint = getGraphQLEndpoint(chain)\n\n // Convert addresses to DataKey format expected by decoder\n const dataKeys = addresses as any[] // DataKey is a hex string type\n\n // Fetch using decoder package\n const results = await fetchMultipleAddresses(dataKeys, graphqlEndpoint)\n\n // Process results and resolve promises\n for (const address of addresses) {\n const normalizedAddress = address.toLowerCase() as any\n const enhanced: EnhancedInfo | undefined = results.get(normalizedAddress)\n\n let result: ResolvedAddress\n\n if (enhanced) {\n // Just pass through the enhanced data as-is - no need to restructure\n const profileImages = (enhanced as Record<string, any>).profileImages\n const resolvedData = {\n ...enhanced,\n hasProfile: !!(enhanced.name || profileImages?.length),\n }\n\n // Cache the result with chainId\n cacheAddressForChain(address, resolvedData, chainId)\n\n result = {\n ...resolvedData,\n address,\n truncatedAddress: truncateAddress(address),\n }\n } else {\n // No profile found\n result = {\n address,\n truncatedAddress: truncateAddress(address),\n hasProfile: false,\n }\n\n // Cache negative result with chainId\n cacheAddressForChain(address, { hasProfile: false }, chainId)\n }\n\n // Resolve the promise\n const resolver = state.batchResolvers.get(normalizedAddress)\n if (resolver) {\n resolver(result)\n state.batchResolvers.delete(normalizedAddress)\n }\n }\n } catch (error) {\n console.warn(\n 'Batch address resolution failed (falling back to API):',\n error\n )\n\n // Fallback to original API approach if decoder package fails\n try {\n const response = await fetch('/api/resolveAddresses', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n addresses,\n chainId: chainId,\n }),\n })\n\n if (!response.ok) {\n throw new Error(`API fallback failed: ${response.status}`)\n }\n\n const data = await response.json()\n\n // Process API results\n for (const address of addresses) {\n const normalizedAddress = address.toLowerCase()\n const resolved = data.resolved?.[normalizedAddress]\n\n let result: ResolvedAddress\n\n if (resolved) {\n const resolvedData = {\n name: resolved.name,\n profileImage: resolved.profileImage,\n hasProfile: !!(resolved.name || resolved.profileImage),\n }\n\n cacheAddressForChain(address, resolvedData, chainId)\n\n result = {\n address,\n truncatedAddress: truncateAddress(address),\n ...resolvedData,\n }\n } else {\n result = {\n address,\n truncatedAddress: truncateAddress(address),\n hasProfile: false,\n }\n cacheAddressForChain(address, { hasProfile: false }, chainId)\n }\n\n const resolver = state.batchResolvers.get(normalizedAddress)\n if (resolver) {\n resolver(result)\n state.batchResolvers.delete(normalizedAddress)\n }\n }\n } catch (fallbackError) {\n console.warn('Both GraphQL and API resolution failed:', fallbackError)\n\n // Return fallbacks for all addresses\n for (const address of addresses) {\n const fallback: ResolvedAddress = {\n address,\n truncatedAddress: truncateAddress(address),\n hasProfile: false,\n }\n\n cacheAddressForChain(address, { hasProfile: false }, chainId)\n\n const resolver = state.batchResolvers.get(address.toLowerCase())\n if (resolver) {\n resolver(fallback)\n state.batchResolvers.delete(address.toLowerCase())\n }\n }\n }\n } finally {\n // Always reset processing flag\n state.isProcessing = false\n }\n}\n\n/**\n * Chain-aware address cache functions\n */\nfunction cacheAddressForChain(\n address: string,\n data: any,\n chainId: number\n): void {\n const key = `${address.toLowerCase()}:${chainId}`\n cacheAddress(key, data)\n}\n\nfunction getCachedAddressForChain(\n address: string,\n chainId: number\n): any | null {\n const key = `${address.toLowerCase()}:${chainId}`\n return getCachedAddress(key)\n}\n\n/**\n * Get effective chain ID from parameter or current signal\n */\nasync function getEffectiveChainId(chainId?: number): Promise<number> {\n if (chainId !== undefined) return chainId\n\n // Initialize chain signal if needed\n await initializeChainSignal()\n\n // Get from signal or fall back to global config\n const currentChain = currentChainSignal.value\n if (currentChain) {\n return currentChain.id\n }\n\n // Final fallback to global config\n const config = getLuksoConfig()\n return config.chainId\n}\n\n/**\n * Resolve a single address using batched resolution\n * Returns immediately with cached data or fallback, then updates with resolved data\n * Handles both plain addresses and address-tokenId composite format (with - separator)\n */\nexport async function resolveAddress(\n address: string,\n chainId?: number\n): Promise<ResolvedAddress> {\n const effectiveChainId = await getEffectiveChainId(chainId)\n const normalizedAddress = address.toLowerCase()\n\n // Always provide truncated fallback using the original address\n const fallback: ResolvedAddress = {\n address,\n truncatedAddress: truncateAddress(address),\n hasProfile: false,\n }\n\n // Return fallback immediately if resolution disabled\n if (!isAddressResolutionEnabled()) {\n return fallback\n }\n\n // Check cache first (chain-aware)\n const cached = getCachedAddressForChain(address, effectiveChainId)\n if (cached) {\n return {\n ...fallback,\n ...cached,\n hasProfile: !!(cached.name || cached.profileImage),\n }\n }\n\n const state = getBatchState(effectiveChainId)\n\n // Check if resolution is already pending for this chain\n const existingPromise = state.pendingResolutions.get(normalizedAddress)\n if (existingPromise) {\n return existingPromise\n }\n\n // Safety check: if we already have this address in the batch queue, return a fast fallback\n if (state.batchQueue.has(normalizedAddress)) {\n return Promise.resolve(fallback)\n }\n\n // Create new resolution promise\n const resolutionPromise = new Promise<ResolvedAddress>((resolve) => {\n // Add full address to batch queue (supports address-tokenId format with -)\n state.batchQueue.add(normalizedAddress)\n state.batchResolvers.set(normalizedAddress, resolve)\n\n // Clear existing timeout\n if (state.batchTimeout) {\n clearTimeout(state.batchTimeout)\n }\n\n // Set new timeout for batch processing (only if not already processing)\n if (!state.isProcessing) {\n state.batchTimeout = setTimeout(() => {\n state.batchTimeout = null\n processBatch(effectiveChainId)\n }, BATCH_DELAY)\n\n // Process immediately if batch is full\n if (state.batchQueue.size >= BATCH_SIZE) {\n if (state.batchTimeout) {\n clearTimeout(state.batchTimeout)\n state.batchTimeout = null\n }\n processBatch(effectiveChainId)\n }\n }\n })\n\n // Store the promise to avoid duplicate requests\n state.pendingResolutions.set(normalizedAddress, resolutionPromise)\n\n // Clean up after resolution\n resolutionPromise.finally(() => {\n state.pendingResolutions.delete(normalizedAddress)\n })\n\n return resolutionPromise\n}\n\n/**\n * Resolve multiple addresses\n */\nexport async function resolveAddresses(\n addresses: string[],\n chainId?: number\n): Promise<Map<string, ResolvedAddress>> {\n const results = new Map<string, ResolvedAddress>()\n\n // Resolve all addresses in parallel using the batched resolver\n const resolutionPromises = addresses.map(async (address) => {\n const resolved = await resolveAddress(address, chainId)\n results.set(address.toLowerCase(), resolved)\n })\n\n await Promise.all(resolutionPromises)\n return results\n}\n\n/**\n * Simple reactive state for frameworks to implement\n * Each framework will wrap this with their reactivity system\n */\nexport interface AddressResolutionState {\n resolved: ResolvedAddress | null\n loading: boolean\n error: string | null\n}\n\n/**\n * Create initial state\n */\nexport function createAddressResolutionState(): AddressResolutionState {\n return {\n resolved: null,\n loading: false,\n error: null,\n }\n}\n\n/**\n * Framework-agnostic resolution function that updates state\n */\nexport async function resolveAddressWithState(\n address: string,\n _state: AddressResolutionState,\n updateCallback: (newState: Partial<AddressResolutionState>) => void,\n chainId?: number\n): Promise<void> {\n // Start loading\n updateCallback({ loading: true, error: null })\n\n try {\n const resolved = await resolveAddress(address, chainId)\n updateCallback({\n resolved,\n loading: false,\n error: null,\n })\n } catch (error) {\n updateCallback({\n loading: false,\n error: error instanceof Error ? error.message : 'Resolution failed',\n })\n }\n}\n","// Main exports for the decoder-headless package\n\nexport type {\n AddressImageData,\n AddressResolutionState,\n ImageLoadOptions,\n ImageResult,\n LuksoConfig,\n ResolvedAddress,\n UseTransactionViewOptions,\n UseTransactionViewResult,\n} from './composables'\nexport * from './composables'\nexport {\n findBestTransactionView,\n useTransactionView,\n} from './composables'\n// Configuration and address resolution (framework-agnostic)\nexport * from './config/lukso-config'\nexport * from './hooks/useAddressQuery'\nexport * from './hooks/useAddressResolution'\nexport * from './registry'\n// Convenience re-exports for common use cases\nexport {\n getGlobalLoader,\n getGlobalRegistry,\n} from './registry'\nexport type {\n DecoderRecordForSelection,\n ViewContext,\n ViewDefinition,\n ViewMatch,\n ViewMatchCriteria,\n} from './types'\nexport * from './types'\nexport * from './utils'\n// Release update\n// build 2\n","// Configuration exports\nexport type { LuksoConfig } from '../config/lukso-config'\nexport {\n cacheAddress,\n clearAddressCache,\n getCachedAddress,\n getLuksoConfig,\n isAddressResolutionEnabled,\n setLuksoConfig,\n useLuksoMainnet,\n useLuksoTestnet,\n} from '../config/lukso-config'\n// Address resolution exports\nexport type {\n AddressResolutionState,\n ResolvedAddress,\n} from '../hooks/useAddressResolution'\nexport {\n createAddressResolutionState,\n resolveAddress,\n resolveAddresses,\n resolveAddressWithState,\n} from '../hooks/useAddressResolution'\nexport type {\n ViewContext,\n ViewContextRequirements,\n ViewVariant,\n} from '../types/view-contexts'\nexport type { ViewMatch } from '../types/view-matching'\nexport type {\n AddressImageData,\n ImageLoadOptions,\n ImageResult,\n} from './use-image-loader'\nexport {\n useAddressResolver,\n useImageLoader,\n} from './use-image-loader'\n// Transaction playback exports\nexport type {\n PlaybackIndexResult,\n TransactionPlaybackOptions,\n TransactionPlaybackState,\n} from './use-transaction-playback'\nexport {\n createTransactionPlayback,\n getValidPlaybackIndices,\n isValidPlaybackIndex,\n useTransactionPlayback,\n} from './use-transaction-playback'\nexport type {\n UseTransactionViewOptions,\n UseTransactionViewResult,\n} from './use-transaction-view'\nexport {\n findAllTransactionViews,\n findBestTransactionView,\n useTransactionView,\n} from './use-transaction-view'\n","import type { ImageData } from '@lukso/transaction-decoder'\n\n// Force cache invalidation\nconsole.log(\n '🔥 LOADING NEW useAddressResolver CODE - should see GraphQL integration'\n)\n\n/**\n * Image loading configuration for different contexts\n */\nexport interface ImageLoadOptions {\n width?: number\n height?: number\n dpr?: number\n index?: number\n}\n\n/**\n * Resolved image result\n */\nexport interface ImageResult {\n src: string\n width?: number\n height?: number\n}\n\n/**\n * Address/Profile data structure for image resolution\n * Note: GraphQL pluralizes field names (icons, not icon)\n */\nexport interface AddressImageData {\n profileImages?: ImageData[]\n avatar?: ImageData[]\n icons?: ImageData[] // GraphQL pluralizes to \"icons\"\n images?: ImageData[]\n __gqltype?: string\n}\n\n// Image loading cache for preventing duplicate requests\nconst imageLoadCache = new Map<string, Promise<ImageResult | null>>()\n\n/**\n * Generate cache key for image loading based on image data and options\n */\nfunction getImageCacheKey(imageData: any[], options: ImageLoadOptions): string {\n // Create a stable key based on the image data sources and size requirements\n const imageUrls = imageData\n .filter((img) => img?.url || img?.src)\n .map((img) => img.url || img.src)\n .sort()\n .join(',')\n\n const sizeKey = `${options.width || 32}x${options.height || options.width || 32}@${options.dpr || 1}`\n\n return `${imageUrls}-${sizeKey}`\n}\n\n/**\n * Composable for loading images from various sources\n * Extracted from Vue AddressView component for framework-agnostic use\n */\nexport function useImageLoader() {\n /**\n * Load image from GraphQL-resolved image groups using proper size selection\n */\n async function loadImage(\n imageData: any[],\n options: ImageLoadOptions = {}\n ): Promise<ImageResult | null> {\n try {\n if (!imageData || imageData.length === 0) {\n return null\n }\n\n // Default options\n const loadOptions = {\n width: options.width || 32,\n height: options.height || options.width || 32,\n dpr:\n options.dpr ||\n (typeof window !== 'undefined' ? window.devicePixelRatio : 1),\n ignoreHead: true, // Skip HEAD requests in component context\n }\n\n // Check cache first to prevent duplicate requests\n const cacheKey = getImageCacheKey(imageData, loadOptions)\n const cachedPromise = imageLoadCache.get(cacheKey)\n if (cachedPromise) {\n console.log('📸 loadImage: Using cached promise for', cacheKey)\n return cachedPromise\n }\n\n console.log(\n '📸 loadImage: Creating new request for',\n imageData.length,\n 'options:',\n loadOptions\n )\n\n // Create and cache the loading promise\n const loadingPromise = (async (): Promise<ImageResult | null> => {\n // Import the proper getImage function from decoder package\n const { getImage } = await import('@lukso/transaction-decoder')\n\n const result = await getImage(imageData, loadOptions)\n\n if (result?.src) {\n console.log('📸 loadImage: Selected image:', result.src)\n return {\n src: result.src,\n width: result.width,\n height: result.height,\n }\n }\n\n return null\n })()\n\n // Cache the promise\n imageLoadCache.set(cacheKey, loadingPromise)\n\n // Clean up cache on completion (success or failure)\n loadingPromise.finally(() => {\n // Keep successful results cached, remove failures\n loadingPromise\n .then((result) => {\n if (!result) {\n imageLoadCache.delete(cacheKey)\n }\n })\n .catch(() => {\n imageLoadCache.delete(cacheKey)\n })\n })\n\n return loadingPromise\n } catch (error) {\n console.warn('Failed to load image:', error)\n return null\n }\n }\n\n /**\n * Get profile/avatar image from address data\n * Priority differs based on type:\n * - Profiles: profileImages first\n * - NFTs/Contracts: icons first (GraphQL pluralizes to \"icons\"), then images\n * - Avatars are from other contracts (not used yet)\n */\n async function loadProfileImage(\n addressData: AddressImageData,\n options: ImageLoadOptions = {}\n ): Promise<ImageResult | null> {\n // For Profiles, prioritize profileImages\n if (addressData.__gqltype === 'Profile') {\n // Try profileImages first\n if (addressData.profileImages?.length) {\n const result = await loadImage(addressData.profileImages, options)\n if (result) return result\n }\n // Fallback to icons\n if (addressData.icons?.length) {\n const result = await loadImage(addressData.icons, options)\n if (result) return result\n }\n // Fallback to images\n if (addressData.images?.length) {\n return loadImage(addressData.images, options)\n }\n return null\n }\n\n // For NFTs/Contracts, prioritize icons, fallback to images\n // Tokens/Assets will never have profileImages, so only check icons and images\n // Try icons first\n if (addressData.icons?.length) {\n const result = await loadImage(addressData.icons, options)\n if (result) return result\n }\n // Fallback to images\n if (addressData.images?.length) {\n return loadImage(addressData.images, options)\n }\n\n return null\n }\n\n /**\n * Load background image from resolved address data\n */\n async function loadBackgroundImage(\n addressData: AddressImageData & { backgroundImages?: any[] },\n options: ImageLoadOptions = {}\n ): Promise<ImageResult | null> {\n const imageGroup = addressData.backgroundImages || []\n return loadImage(imageGroup, options)\n }\n\n /**\n * Get fallback image based on address type\n */\n function getFallbackImage(addressData: AddressImageData): ImageResult {\n const isProfile = addressData.__gqltype === 'Profile'\n return {\n src: isProfile\n ? '/assets/images/profile-default.svg'\n : '/assets/images/token-default.svg',\n }\n }\n\n /**\n * Determine if address represents a contract (has square icon)\n */\n function isContractAddress(addressData: AddressImageData): boolean {\n return addressData.__gqltype !== 'Profile'\n }\n\n return {\n loadImage,\n loadProfileImage,\n loadBackgroundImage,\n getFallbackImage,\n isContractAddress,\n }\n}\n\n/**\n * Composable for address resolution and formatting\n * Connected to decoder package's GraphQL AddressResolver\n */\nexport function useAddressResolver() {\n /**\n * Resolve address data using decoder package integration\n * Uses the batched address resolution from useAddressResolution\n */\n async function resolveAddress(address: string): Promise<any> {\n console.log('🔥 useAddressResolver.resolveAddress called with:', address)\n\n try {\n // Import and use the batched resolution from the hooks\n const { resolveAddress: batchedResolve } = await import(\n '../hooks/useAddressResolution'\n )\n\n console.log('🔥 useAddressResolver: calling batchedResolve...')\n const resolved = await batchedResolve(address)\n console.log('🔥 useAddressResolver: batchedResolve returned:', resolved)\n\n // Always return something, even if no profile - this ensures we don't return null unnecessarily\n const result = {\n // Preserve all image arrays from GraphQL\n ...resolved,\n // Override with computed values only if not already set by GraphQL\n address: resolved.address,\n name: resolved.name || '',\n __gqltype:\n resolved.__gqltype || (resolved.hasProfile ? 'Profile' : 'Contract'),\n }\n\n console.log('🔥 useAddressResolver: returning result:', result)\n return result\n } catch (error) {\n console.error('🔥 useAddressResolver: Failed to resolve address:', error)\n\n // Return a fallback instead of null\n return {\n address,\n name: '',\n __gqltype: 'Contract',\n profileImages: [],\n avatar: [],\n icon: [],\n }\n }\n }\n\n /**\n * Format address display name from resolved data\n */\n function formatDisplayName(addressData: any): string {\n const baseName =\n addressData.name?.toLowerCase?.() ||\n addressData.lsp4TokenName ||\n addressData.baseAsset?.lsp4TokenName ||\n ''\n\n const symbol =\n addressData.lsp4TokenSymbol ||\n addressData.baseAsset?.lsp4TokenSymbol ||\n ''\n\n return symbol ? `${baseName} (${symbol})` : baseName\n }\n\n /**\n * Get address prefix based on type\n */\n function getAddressPrefix(addressData: any): string {\n return addressData.__gqltype !== 'Profile' ? '🪙 ' : '@'\n }\n\n /**\n * Check if address should show name colors\n */\n function shouldShowNameColor(addressData: any): boolean {\n return addressData.__gqltype === 'Profile'\n }\n\n return {\n resolveAddress,\n formatDisplayName,\n getAddressPrefix,\n shouldShowNameColor,\n }\n}\n","import type { DecoderResult } from '@lukso/transaction-decoder'\nimport type {\n DecoderRecordForSelection,\n ViewDefinition,\n ViewMatch,\n ViewMatchCriteria,\n ViewMatchOptions,\n} from '../types/view-matching'\n\n/**\n * Weights for different matching criteria (higher = more important)\n * Context is optional - only weighted when both view and request specify context\n */\nexport const CRITERIA_WEIGHTS = {\n recordType: 0.25, // Most specific to transaction type\n functionName: 0.2, // Function-level specificity\n context: 0.2, // Context specificity (when opt-in)\n standard: 0.15, // LSP standard specificity\n contractAddress: 0.1, // Contract-specific logic\n contextRequirements: 0.05, // Context requirement matching\n chainId: 0.03, // Network-specific behavior\n customMatcher: 0.02, // Custom logic (lowest weight due to unpredictability)\n} as const\n\n/**\n * Calculate how well a view matches a transaction and context\n *\n * Context matching is opt-in:\n * - If view specifies context criteria, request MUST provide matching context\n * - If view has no context criteria, it matches any context (universal view)\n * - If request has no context, context-specific views are deprioritized\n *\n * Note: For batch operations (executeBatch, setDataBatch, etc.), this matches\n * against the parent transaction. Future enhancement could include matching\n * against child transactions for more granular view selection.\n */\nexport function calculateMatchScore(\n transaction: DecoderResult,\n view: ViewDefinition,\n options?: Pick<ViewMatchOptions, 'context' | 'contextRequirements'>\n): { score: number; matchedCriteria: (keyof ViewMatchCriteria)[] } {\n const { criteria } = view\n const matchedCriteria: (keyof ViewMatchCriteria)[] = []\n let totalWeight = 0\n let matchedWeight = 0\n\n // Check each criterion and accumulate scores\n for (const [criterion, weight] of Object.entries(CRITERIA_WEIGHTS)) {\n const criterionKey = criterion as keyof ViewMatchCriteria\n const criterionValue = criteria[criterionKey]\n\n if (criterionValue === undefined) continue\n\n totalWeight += weight\n\n // Special handling for customMatcher - use match count\n if (\n criterionKey === 'customMatcher' &&\n typeof criterionValue === 'function'\n ) {\n try {\n const matchCount = criterionValue(transaction)\n if (matchCount > 0) {\n matchedCriteria.push(criterionKey)\n // Normalize match count to 0-1 range (cap at 10 conditions)\n const normalizedScore = Math.min(matchCount / 10, 1)\n matchedWeight += weight * normalizedScore\n }\n } catch (error) {\n console.warn('Custom matcher threw error:', error)\n }\n continue\n }\n\n if (\n doesCriterionMatch(transaction, criterionKey, criterionValue, options)\n ) {\n matchedCriteria.push(criterionKey)\n matchedWeight += weight\n }\n }\n\n // Handle context opt-in logic\n const viewHasContext = criteria.context !== undefined\n const requestHasContext = options?.context !== undefined\n\n if (viewHasContext && !requestHasContext) {\n // View requires specific context, but none provided - penalize heavily\n matchedWeight *= 0.1 // Reduce score by 90%\n } else if (!viewHasContext && requestHasContext) {\n // Universal view matching specific context - slight penalty to prefer context-specific views\n matchedWeight *= 0.9 // Reduce score by 10%\n }\n\n // If no criteria are defined, this view doesn't match\n if (totalWeight === 0) return { score: 0, matchedCriteria: [] }\n\n // Calculate final score (0-1)\n const score = matchedWeight / totalWeight\n\n return { score, matchedCriteria }\n}\n\n/**\n * Check if a specific criterion matches the transaction\n */\nfunction doesCriterionMatch(\n transaction: DecoderResult,\n criterion: keyof ViewMatchCriteria,\n criterionValue: any,\n options?: Pick<ViewMatchOptions, 'context' | 'contextRequirements'>\n): boolean {\n switch (criterion) {\n case 'recordType':\n return matchesStringOrArray(\n (transaction as DecoderRecordForSelection).recordType,\n criterionValue\n )\n\n case 'functionName':\n return matchesStringOrArray(\n (transaction as DecoderRecordForSelection).functionName,\n criterionValue\n )\n\n case 'standard':\n return matchesStringOrArray(\n (transaction as DecoderRecordForSelection).standard,\n criterionValue\n )\n\n case 'contractAddress':\n return matchesStringOrArray(\n (transaction as DecoderRecordForSelection).contractAddress,\n criterionValue\n )\n\n case 'chainId':\n return matchesNumberOrArray(transaction.chainId, criterionValue)\n\n case 'context':\n if (!options?.context) return false // No context provided, can't match\n return matchesStringOrArray(options.context, criterionValue)\n\n case 'contextRequirements':\n if (!options?.contextRequirements || !criterionValue) return false\n return areContextRequirementsCompatible(\n options.contextRequirements,\n criterionValue\n )\n\n case 'customMatcher':\n if (typeof criterionValue === 'function') {\n try {\n const matchCount = criterionValue(transaction)\n // Match if any conditions matched (> 0)\n // The actual count contributes to the score in calculateMatchScore\n return matchCount > 0\n } catch (error) {\n console.warn('Custom matcher threw error:', error)\n return false\n }\n }\n return false\n\n default:\n return false\n }\n}\n\n/**\n * Helper to match string values against string or array criteria\n */\nfunction matchesStringOrArray(\n value: string | undefined,\n criteria: string | string[]\n): boolean {\n if (!value || !criteria) return false\n\n if (Array.isArray(criteria)) {\n return criteria.includes(value)\n }\n\n return value === criteria\n}\n\n/**\n * Helper to match number values against number or array criteria\n */\nfunction matchesNumberOrArray(\n value: number | undefined,\n criteria: number | number[]\n): boolean {\n if (value === undefined || criteria === undefined) return false\n\n if (Array.isArray(criteria)) {\n return criteria.includes(value)\n }\n\n return value === criteria\n}\n\n/**\n * Check if context requirements are compatible\n */\nfunction areContextRequirementsCompatible(\n requested: any,\n viewRequirements: any\n): boolean {\n // Simple compatibility check - can be extended\n if (requested.detailLevel && viewRequirements.detailLevel) {\n const detailOrder = ['minimal', 'summary', 'full', 'debug']\n const requestedLevel = detailOrder.indexOf(requested.detailLevel)\n const viewLevel = detailOrder.indexOf(viewRequirements.detailLevel)\n if (viewLevel < requestedLevel) return false\n }\n\n if (requested.maxHeight && viewRequirements.maxHeight) {\n if (viewRequirements.maxHeight > requested.maxHeight) return false\n }\n\n return true\n}\n\n/**\n * Calculate native framework priority bonus\n *\n * Native framework implementations (Vue, React Native) get priority over Lit fallbacks:\n * - Vue: +0.15 bonus when view has Vue implementation\n * - React Native (rn): +0.15 bonus when view has RN implementation\n * - Lit: NO bonus (Lit is the universal fallback)\n *\n * This ensures that when both native and Lit views exist for the same transaction:\n * - Vue app prefers Vue view (Vue score + 0.15 > Lit score)\n * - React Native app prefers RN view (RN score + 0.15 > Lit score)\n * - Other frameworks use Lit view (universal compatibility)\n */\nfunction calculateNativeFrameworkBonus(\n view: ViewDefinition,\n requestedFramework: 'lit' | 'vue' | 'rn'\n): number {\n // Lit gets no bonus - it's the universal fallback\n if (requestedFramework === 'lit') {\n return 0\n }\n\n // Vue gets bonus if view has Vue implementation\n if (requestedFramework === 'vue' && view.frameworks.vue) {\n return 0.15\n }\n\n // React Native gets bonus if view has RN implementation\n if (requestedFramework === 'rn' && view.frameworks.rn) {\n return 0.15\n }\n\n return 0\n}\n\n/**\n * Find and score all matching views for a transaction\n *\n * Views are matched and sorted by:\n * 1. Match score (how well criteria match the transaction)\n * 2. Native framework bonus (Vue/RN get +0.15, Lit gets 0)\n * 3. View priority (manually set priority)\n *\n * This ensures that native framework views are preferred when available,\n * while Lit serves as a universal fallback.\n */\nexport function findMatchingViews(\n transaction: DecoderResult,\n views: ViewDefinition[],\n options: ViewMatchOptions\n): ViewMatch[] {\n const matches: ViewMatch[] = []\n const minScore = options.minScore ?? 0\n\n for (const view of views) {\n // Skip if framework is not supported\n if (!view.frameworks[options.framework]) {\n continue\n }\n\n const { score, matchedCriteria } = calculateMatchScore(transaction, view, {\n context: options.context,\n contextRequirements: options.contextRequirements,\n })\n\n // Skip if score is below threshold\n if (score < minScore) {\n continue\n }\n\n // Apply native framework bonus (Vue/RN only, NOT Lit)\n const frameworkBonus = calculateNativeFrameworkBonus(\n view,\n options.framework\n )\n const finalScore = Math.min(1, score + frameworkBonus)\n\n const match: ViewMatch = {\n view,\n score: finalScore,\n matchedCriteria,\n frameworkConfig: options.includeFrameworkConfig\n ? view.frameworks[options.framework]\n : undefined,\n }\n\n matches.push(match)\n }\n\n // Sort by score (descending), then by priority (descending)\n matches.sort((a, b) => {\n if (a.score !== b.score) {\n return b.score - a.score\n }\n return b.view.priority - a.view.priority\n })\n\n // Limit results if requested\n if (options.maxMatches) {\n return matches.slice(0, options.maxMatches)\n }\n\n return matches\n}\n\n/**\n * TODO: Future enhancement for batch operations\n *\n * For batch operations like executeBatch, setDataBatch, we might want to:\n * 1. Match against the batch container (current behavior)\n * 2. Also match against child transactions for more specific views\n * 3. Allow views to specify whether they handle batches vs individual items\n * 4. Support composite views that render both batch info + child items\n */\n","import type { DecoderResult } from '@lukso/transaction-decoder'\nimport type {\n ViewDefinition,\n ViewMatch,\n ViewMatchOptions,\n ViewRegistry,\n} from '../types/view-matching'\nimport { findMatchingViews } from '../utils/view-matcher'\n\n/**\n * Default view registry implementation\n */\nexport class DefaultViewRegistry implements ViewRegistry {\n private views = new Map<string, ViewDefinition>()\n\n register(view: ViewDefinition): void {\n if (this.views.has(view.id)) {\n console.warn(\n `View with id \"${view.id}\" is already registered. Overwriting.`\n )\n }\n\n this.views.set(view.id, view)\n }\n\n unregister(viewId: string): void {\n this.views.delete(viewId)\n }\n\n getAllViews(): ViewDefinition[] {\n return Array.from(this.views.values())\n }\n\n findMatches(\n transaction: DecoderResult,\n options: ViewMatchOptions\n ): ViewMatch[] {\n const allViews = this.getAllViews()\n return findMatchingViews(transaction, allViews, options)\n }\n\n getView(viewId: string): ViewDefinition | undefined {\n return this.views.get(viewId)\n }\n\n clear(): void {\n this.views.clear()\n }\n\n /**\n * Get the best matching view (highest score) for a transaction\n */\n getBestMatch(\n transaction: DecoderResult,\n options: ViewMatchOptions\n ): ViewMatch | null {\n const matches = this.findMatches(transaction, { ...options, maxMatches: 1 })\n return matches[0] || null\n }\n\n /**\n * Bulk register multiple views\n */\n registerMany(views: ViewDefinition[]): void {\n for (const view of views) {\n this.register(view)\n }\n }\n\n /**\n * Get stats about registered views\n */\n getStats(): {\n totalViews: number\n viewsByFramework: Record<string, number>\n viewsByRecordType: Record<string, number>\n } {\n const allViews = this.getAllViews()\n const totalViews = allViews.length\n\n const viewsByFramework: Record<string, number> = {}\n const viewsByRecordType: Record<string, number> = {}\n\n for (const view of allViews) {\n // Count framework support\n for (const framework of Object.keys(view.frameworks)) {\n viewsByFramework[framework] = (viewsByFramework[framework] || 0) + 1\n }\n\n // Count by record type\n const recordType = view.criteria.recordType\n if (recordType) {\n const types = Array.isArray(recordType) ? recordType : [recordType]\n for (const type of types) {\n viewsByRecordType[type] = (viewsByRecordType[type] || 0) + 1\n }\n }\n }\n\n return {\n totalViews,\n viewsByFramework,\n viewsByRecordType,\n }\n }\n}\n\n/**\n * Global registry instance\n */\nlet globalRegistry: ViewRegistry | null = null\n\n/**\n * Get or create the global view registry\n */\nexport function getGlobalRegistry(): ViewRegistry {\n if (!globalRegistry) {\n globalRegistry = new DefaultViewRegistry()\n }\n return globalRegistry\n}\n\n/**\n * Set a custom global registry (useful for testing or custom implementations)\n */\nexport function setGlobalRegistry(registry: ViewRegistry): void {\n globalRegistry = registry\n}\n\n/**\n * Reset the global registry (mainly for testing)\n */\nexport function resetGlobalRegistry(): void {\n globalRegistry = null\n}\n","import type { DecoderResult } from '@lukso/transaction-decoder'\nimport type { Chain } from 'viem'\nimport { getGlobalRegistry } from '../registry/view-registry'\nimport type {\n ViewMatch,\n ViewMatchOptions,\n ViewRegistry,\n} from '../types/view-matching'\n\n/**\n * Transaction Playback System\n *\n * Provides index-based access to transaction views with smart handling of batches:\n *\n * **Single Transaction:**\n * - Index 0: The transaction itself\n * - Index 1: The transaction itself (same as 0)\n * - Index 2+: null\n *\n * **Batch Transaction (setDataBatch, executeBatch):**\n * - Index 0: Summary/expandable view of the batch\n * - Index 1: First child transaction\n * - Index 2: Second child transaction\n * - Index N: Nth child transaction\n *\n * This design allows UI flexibility:\n * - Always use index 1 to skip batch summaries\n * - Use index 0 to show batch overview (optional)\n * - Navigate batch children by index\n */\n\n/**\n * Options for transaction playback\n */\nexport interface TransactionPlaybackOptions extends Partial<ViewMatchOptions> {\n /** Custom registry to use instead of global */\n registry?: ViewRegistry\n /** Fallback view ID if no matches found */\n fallbackViewId?: string\n /** Chain for address resolution */\n chain?: Chain\n}\n\n/**\n * Result of selecting a view at a specific index\n */\nexport interface PlaybackIndexResult {\n /** The selected view match (or null if invalid index) */\n match: ViewMatch | null\n /** The transaction data for this index */\n transaction: DecoderResult | null\n /** Index information */\n indexInfo: {\n /** Requested index */\n requested: number\n /** Actual index in children array (for batches) */\n childIndex: number | null\n /** Whether this is a batch summary view (index 0 of batch) */\n isBatchSummary: boolean\n /** Whether this is a valid index */\n isValid: boolean\n }\n /** Batch information (if applicable) */\n batchInfo: {\n /** Whether the root transaction is a batch */\n isBatch: boolean\n /** Total number of children in batch (0 if not batch) */\n childCount: number\n /** Available indices (e.g., [0, 1, 2, 3] for 3-child batch) */\n availableIndices: number[]\n }\n}\n\n/**\n * Complete playback state for a transaction\n */\nexport interface TransactionPlaybackState {\n /** The root transaction */\n rootTransaction: DecoderResult\n /** Whether this is a batch transaction */\n isBatch: boolean\n /** Child transactions (empty if not batch) */\n children: DecoderResult[]\n /** Total count of available indices */\n indexCount: number\n /** Batch information */\n batchInfo: {\n /** Whether the root transaction is a batch */\n isBatch: boolean\n /** Total number of children in batch (0 if not batch) */\n childCount: number\n /** Available indices (e.g., [0, 1, 2, 3] for 3-child batch) */\n availableIndices: number[]\n }\n /** Get view match for a specific index */\n getViewAtIndex: (index: number) => PlaybackIndexResult\n /** Get all available views */\n getAllViews: () => PlaybackIndexResult[]\n}\n\n/**\n * Check if a transaction is a batch transaction\n *\n * Only executeBatch is a navigable batch where:\n * - Index 0 shows batch summary\n * - Index 1+ shows individual child transactions\n *\n * setDataBatch is NOT a batch - it's a single transaction with a special view\n * that renders all key/value pairs from children.\n */\nfunction isBatchTransaction(transaction: DecoderResult): boolean {\n return transaction.resultType === 'executeBatch'\n}\n\n/**\n * Get children from a batch transaction\n */\nfunction getBatchChildren(transaction: DecoderResult): DecoderResult[] {\n if (!isBatchTransaction(transaction)) {\n return []\n }\n return (transaction as any).children || []\n}\n\n/**\n * Core function to select view at a specific index\n */\nfunction selectViewAtIndex(\n rootTransaction: DecoderResult,\n index: number,\n options: TransactionPlaybackOptions\n): PlaybackIndexResult {\n const {\n registry = getGlobalRegistry(),\n framework = 'lit',\n fallbackViewId,\n minScore = 0,\n includeFrameworkConfig = true,\n } = options\n\n const isBatch = isBatchTransaction(rootTransaction)\n const children = getBatchChildren(rootTransaction)\n const childCount = children.length\n\n // Initialize result\n const result: PlaybackIndexResult = {\n match: null,\n transaction: null,\n indexInfo: {\n requested: index,\n childIndex: null,\n isBatchSummary: false,\n isValid: false,\n },\n batchInfo: {\n isBatch,\n childCount,\n availableIndices: [],\n },\n }\n\n // Calculate available indices\n if (isBatch) {\n // Batch: 0 (summary) + N children\n result.batchInfo.availableIndices = Array.from(\n { length: childCount + 1 },\n (_, i) => i\n )\n } else {\n // Single: 0 and 1 both map to the transaction\n result.batchInfo.availableIndices = [0, 1]\n }\n\n // Validate index\n if (index < 0) {\n return result // Invalid: negative index\n }\n\n // Handle single transaction\n if (!isBatch) {\n if (index === 0 || index === 1) {\n result.indexInfo.isValid = true\n result.transaction = rootTransaction\n\n // Find matching view for the transaction\n const matchOptions: ViewMatchOptions = {\n framework: framework as any,\n minScore,\n maxMatches: 1,\n includeFrameworkConfig,\n }\n\n const matches = registry.findMatches(rootTransaction, matchOptions)\n result.match = matches[0] || null\n\n // Try fallback if no match\n if (!result.match && fallbackViewId) {\n const fallbackView = registry.getView(fallbackViewId)\n if (fallbackView?.frameworks[framework]) {\n result.match = {\n view: fallbackView,\n score: 0,\n matchedCriteria: [],\n frameworkConfig: includeFrameworkConfig\n ? fallbackView.frameworks[framework]\n : undefined,\n }\n }\n }\n\n return result\n }\n\n // Invalid index for single transaction\n return result\n }\n\n // Handle batch transaction\n if (index === 0) {\n // Index 0: Batch summary view\n result.indexInfo.isValid = true\n result.indexInfo.isBatchSummary = true\n result.transaction = rootTransaction\n\n // Find batch summary view\n const matchOptions: ViewMatchOptions = {\n framework: framework as any,\n minScore,\n maxMatches: 1,\n includeFrameworkConfig,\n }\n\n const matches = registry.findMatches(rootTransaction, matchOptions)\n result.match = matches[0] || null\n\n // Try fallback if no match\n if (!result.match && fallbackViewId) {\n const fallbackView = registry.getView(fallbackViewId)\n if (fallbackView?.frameworks[framework]) {\n result.match = {\n view: fallbackView,\n score: 0,\n matchedCriteria: [],\n frameworkConfig: includeFrameworkConfig\n ? fallbackView.frameworks[framework]\n : undefined,\n }\n }\n }\n\n return result\n }\n\n // Index 1+: Child transactions\n const childIndex = index - 1\n if (childIndex >= 0 && childIndex < childCount) {\n result.indexInfo.isValid = true\n result.indexInfo.childIndex = childIndex\n result.transaction = children[childIndex]\n\n // Find matching view for the child transaction\n const matchOptions: ViewMatchOptions = {\n framework: framework as any,\n minScore,\n maxMatches: 1,\n includeFrameworkConfig,\n }\n\n const matches = registry.findMatches(result.transaction, matchOptions)\n result.match = matches[0] || null\n\n // Try fallback if no match\n if (!result.match && fallbackViewId) {\n const fallbackView = registry.getView(fallbackViewId)\n if (fallbackView?.frameworks[framework]) {\n result.match = {\n view: fallbackView,\n score: 0,\n matchedCriteria: [],\n frameworkConfig: includeFrameworkConfig\n ? fallbackView.frameworks[framework]\n : undefined,\n }\n }\n }\n\n return result\n }\n\n // Invalid index for batch\n return result\n}\n\n/**\n * Create a playback state for a transaction\n *\n * @example\n * ```typescript\n * const playback = createTransactionPlayback(transaction, { framework: 'lit' })\n *\n * // For single transaction:\n * playback.getViewAtIndex(0) // Returns the transaction\n * playback.getViewAtIndex(1) // Returns the transaction (same)\n * playback.getViewAtIndex(2) // Returns null (invalid)\n *\n * // For batch transaction:\n * playback.getViewAtIndex(0) // Returns batch summary\n * playback.getViewAtIndex(1) // Returns first child\n * playback.getViewAtIndex(2) // Returns second child\n * ```\n */\nexport function createTransactionPlayback(\n rootTransaction: DecoderResult,\n options: TransactionPlaybackOptions = {}\n): TransactionPlaybackState {\n const isBatch = isBatchTransaction(rootTransaction)\n const children = getBatchChildren(rootTransaction)\n const childCount = children.length\n const indexCount = isBatch ? childCount + 1 : 2 // batch: 0 + N, single: 0 and 1\n\n // Calculate available indices\n const availableIndices = isBatch\n ? Array.from({ length: childCount + 1 }, (_, i) => i) // [0, 1, 2, ...]\n : [0, 1] // Single: 0 and 1 both valid\n\n return {\n rootTransaction,\n isBatch,\n children,\n indexCount,\n batchInfo: {\n isBatch,\n childCount,\n availableIndices,\n },\n getViewAtIndex: (index: number) =>\n selectViewAtIndex(rootTransaction, index, options),\n getAllViews: () => {\n const views: PlaybackIndexResult[] = []\n for (let i = 0; i < indexCount; i++) {\n views.push(selectViewAtIndex(rootTransaction, i, options))\n }\n return views\n },\n }\n}\n\n/**\n * Simplified composable that just returns the view at a specific index\n *\n * @example\n * ```typescript\n * // Vue\n * const index = ref(1) // Always show main transaction, skip batch summaries\n * const result = useTransactionPlayback(transaction, index, { framework: 'lit' })\n *\n * // React\n * const [index, setIndex] = useState(1)\n * const result = useTransactionPlayback(transaction, index, { framework: 'lit' })\n * ```\n */\nexport function useTransactionPlayback(\n rootTransaction: DecoderResult,\n index: number,\n options: TransactionPlaybackOptions = {}\n): PlaybackIndexResult {\n return selectViewAtIndex(rootTransaction, index, options)\n}\n\n/**\n * Helper to check if an index is valid for a transaction\n */\nexport function isValidPlaybackIndex(\n transaction: DecoderResult,\n index: number\n): boolean {\n const isBatch = isBatchTransaction(transaction)\n\n if (!isBatch) {\n return index === 0 || index === 1\n }\n\n const childCount = getBatchChildren(transaction).length\n return index >= 0 && index <= childCount\n}\n\n/**\n * Helper to get the range of valid indices for a transaction\n */\nexport function getValidPlaybackIndices(transaction: DecoderResult): number[] {\n const isBatch = isBatchTransaction(transaction)\n\n if (!isBatch) {\n return [0, 1]\n }\n\n const childCount = getBatchChildren(transaction).length\n return Array.from({ length: childCount + 1 }, (_, i) => i)\n}\n","import type {\n AddressIdentityCache,\n DataKey,\n DecoderResult,\n EnhancedInfo,\n} from '@lukso/transaction-decoder'\nimport {\n fetchMultipleAddresses,\n getGraphQLEndpoint,\n} from '@lukso/transaction-decoder'\nimport type { Chain } from 'viem'\nimport { getGlobalLoader, ViewLoadingError } from '../registry/view-loader'\nimport { getGlobalRegistry } from '../registry/view-registry'\nimport type {\n ViewMatch,\n ViewMatchOptions,\n ViewRegistry,\n} from '../types/view-matching'\n\n/**\n * Options for the transaction view composable\n */\nexport interface UseTransactionViewOptions extends Partial<ViewMatchOptions> {\n /** Custom registry to use instead of global */\n registry?: ViewRegistry\n /** Whether to automatically load the best matching component */\n autoLoad?: boolean\n /** Fallback view ID to use if no matches found */\n fallbackViewId?: string\n /** Whether to resolve addresses for this view (uses transaction.addresses array) */\n resolve?: boolean\n /** Chain for address resolution (required if resolve: true) */\n chain?: Chain\n /** Optional cache adapter for address resolution */\n addressCache?: AddressIdentityCache\n}\n\n/**\n * Result from the transaction view composable\n */\nexport interface UseTransactionViewResult {\n /** All matching views sorted by score */\n matches: ViewMatch[]\n /** The best matching view (highest score) */\n bestMatch: ViewMatch | null\n /** The loaded component (if autoLoad is true) */\n component: any\n /** Loading state */\n isLoading: boolean\n /** Error state */\n error: ViewLoadingError | null\n /** Address resolution loading state */\n isResolvingAddresses: boolean\n /** Resolved address data map (if resolve: true) */\n resolvedAddresses: Record<string, EnhancedInfo>\n /** Function to manually load a specific match */\n loadMatch: (match: ViewMatch) => Promise<any>\n /** Function to load the best match */\n loadBestMatch: () => Promise<any>\n /** Function to refresh matches (useful if registry changes) */\n refreshMatches: () => void\n /** Function to manually trigger address resolution */\n resolveAddresses: () => Promise<void>\n}\n\n/**\n * Framework-agnostic composable for finding and loading transaction views\n *\n * This is the main entry point for the view system. It handles:\n * - Finding matching views based on transaction data\n * - Loading components using the appropriate strategy\n * - Providing a consistent API across all frameworks\n *\n * Usage in Vue:\n * ```ts\n * const { bestMatch, component, isLoading, resolvedAddresses } = useTransactionView(transaction, {\n * framework: 'lit',\n * autoLoad: true,\n * resolve: true, // Auto-resolve addresses from transaction.addresses array\n * chain: lukso, // Required for address resolution\n * addressCache: cache // Optional cache adapter\n * })\n * ```\n *\n * Usage in React/React Native:\n * ```ts\n * const { bestMatch, component, loadBestMatch, resolvedAddresses, isResolvingAddresses } = useTransactionView(transaction, {\n * framework: 'react-native',\n * resolve: true,\n * chain: luksoTestnet,\n * addressCache: myCache\n * })\n * useEffect(() => {\n * loadBestMatch()\n * }, [transaction])\n * ```\n */\nexport function useTransactionView(\n transaction: DecoderResult,\n options: UseTransactionViewOptions\n): UseTransactionViewResult {\n const {\n registry = getGlobalRegistry(),\n autoLoad = false,\n fallbackViewId,\n framework = 'lit',\n minScore = 0,\n maxMatches,\n includeFrameworkConfig = true,\n resolve = false,\n chain,\n addressCache,\n } = options\n\n const loader = getGlobalLoader()\n\n // Internal state (framework-specific implementations will handle reactivity)\n let matches: ViewMatch[] = []\n let bestMatch: ViewMatch | null = null\n let component: any = null\n let isLoading = false\n let error: ViewLoadingError | null = null\n let isResolvingAddresses = false\n let resolvedAddresses: Record<string, EnhancedInfo> = {}\n\n // Find matching views\n const refreshMatches = () => {\n const matchOptions: ViewMatchOptions = {\n framework: framework as any,\n minScore,\n maxMatches,\n includeFrameworkConfig,\n }\n\n matches = registry.findMatches(transaction, matchOptions)\n bestMatch = matches[0] || null\n\n // If no matches and we have a fallback, try to get it\n if (!bestMatch && fallbackViewId) {\n const fallbackView = registry.getView(fallbackViewId)\n if (fallbackView?.frameworks[framework]) {\n bestMatch = {\n view: fallbackView,\n score: 0,\n matchedCriteria: [],\n frameworkConfig: includeFrameworkConfig\n ? fallbackView.frameworks[framework]\n : undefined,\n }\n }\n }\n }\n\n // Load a specific match\n const loadMatch = async (match: ViewMatch): Promise<any> => {\n if (!match.frameworkConfig) {\n throw new ViewLoadingError(\n `No framework config for view \"${match.view.id}\" and framework \"${framework}\"`,\n { type: 'dynamic-import', path: '' },\n {} as any\n )\n }\n\n isLoading = true\n error = null\n\n try {\n const loadedComponent = await loader.loadFromMatch(match)\n component = loadedComponent\n return loadedComponent\n } catch (err) {\n error =\n err instanceof ViewLoadingError\n ? err\n : new ViewLoadingError(\n 'Unknown loading error',\n match.frameworkConfig.loader,\n match.frameworkConfig,\n err instanceof Error ? err : new Error(String(err))\n )\n throw error\n } finally {\n isLoading = false\n }\n }\n\n // Load the best match\n const loadBestMatch = async (): Promise<any> => {\n if (!bestMatch) {\n throw new Error('No matching view found for transaction')\n }\n return loadMatch(bestMatch)\n }\n\n // Address resolution function\n const resolveAddressesFunc = async (): Promise<void> => {\n if (\n !resolve ||\n !transaction.addresses ||\n transaction.addresses.length === 0\n ) {\n return\n }\n\n if (!chain) {\n console.warn(\n 'Address resolution requested but no chain provided. Pass chain option to resolve addresses.'\n )\n return\n }\n\n isResolvingAddresses = true\n\n try {\n // Convert addresses to DataKey format\n const dataKeys: DataKey[] = transaction.addresses\n .filter((addr) => addr && typeof addr === 'string')\n .map((addr) => addr.toLowerCase() as DataKey)\n\n if (dataKeys.length === 0) {\n return\n }\n\n // Get GraphQL endpoint based on chain\n const endpoint = getGraphQLEndpoint(chain)\n\n // Use raw fetchMultipleAddresses with optional cache\n const resolvedMap = await fetchMultipleAddresses(\n dataKeys,\n endpoint,\n addressCache\n )\n\n // Convert Map to Record for easier consumption\n const resolved: Record<string, EnhancedInfo> = {}\n resolvedMap.forEach((enhancedInfo, dataKey) => {\n resolved[dataKey] = enhancedInfo\n })\n\n resolvedAddresses = resolved\n } catch (err) {\n console.error('Address resolution failed:', err)\n } finally {\n isResolvingAddresses = false\n }\n }\n\n // Initialize\n refreshMatches()\n\n // Auto-resolve addresses if requested\n if (resolve) {\n resolveAddressesFunc().catch((err) => {\n console.error('Auto address resolution failed:', err)\n })\n }\n\n // Auto-load if requested\n if (autoLoad && bestMatch) {\n loadBestMatch().catch((err) => {\n console.error('Auto-load failed:', err)\n })\n }\n\n return {\n matches,\n bestMatch,\n component,\n isLoading,\n error,\n isResolvingAddresses,\n resolvedAddresses,\n loadMatch,\n loadBestMatch,\n refreshMatches,\n resolveAddresses: resolveAddressesFunc,\n }\n}\n\n/**\n * Simplified version that just returns the best matching view without loading\n */\nexport function findBestTransactionView(\n transaction: DecoderResult,\n framework: 'lit' | 'rn',\n registry?: ViewRegistry\n): ViewMatch | null {\n const reg = registry || getGlobalRegistry()\n const matches = reg.findMatches(transaction, {\n framework,\n includeFrameworkConfig: true,\n })\n return matches.length > 0 ? matches[0] : null\n}\n\n/**\n * Get all matching views without loading\n */\nexport function findAllTransactionViews(\n transaction: DecoderResult,\n framework: 'lit' | 'rn',\n registry?: ViewRegistry\n): ViewMatch[] {\n const reg = registry || getGlobalRegistry()\n return reg.findMatches(transaction, {\n framework,\n includeFrameworkConfig: true,\n })\n}\n","import type {\n FrameworkViewConfig,\n ViewLoader,\n ViewMatch,\n} from '../types/view-matching'\n\n/**\n * Error thrown when view loading fails\n */\nexport class ViewLoadingError extends Error {\n public readonly loader: ViewLoader\n public readonly config: FrameworkViewConfig\n public override readonly cause?: Error\n\n constructor(\n message: string,\n loader: ViewLoader,\n config: FrameworkViewConfig,\n cause?: Error\n ) {\n super(message)\n this.name = 'ViewLoadingError'\n this.loader = loader\n this.config = config\n this.cause = cause\n }\n}\n\n/**\n * Framework-agnostic view loader that handles different loading strategies\n */\nexport class UniversalViewLoader {\n private cache = new Map<string, any>()\n\n /**\n * Load a component based on the framework configuration\n */\n async loadComponent(config: FrameworkViewConfig): Promise<any> {\n const cacheKey = this.getCacheKey(config)\n\n // Return cached component if available\n if (this.cache.has(cacheKey)) {\n return this.cache.get(cacheKey)\n }\n\n try {\n const component = await this.loadByStrategy(config.loader)\n this.cache.set(cacheKey, component)\n return component\n } catch (error) {\n throw new ViewLoadingError(\n `Failed to load component \"${config.component}\"`,\n config.loader,\n config,\n error instanceof Error ? error : new Error(String(error))\n )\n }\n }\n\n /**\n * Load a component from a view match\n */\n async loadFromMatch(match: ViewMatch): Promise<any> {\n if (!match.frameworkConfig) {\n throw new ViewLoadingError(\n `No framework config available for view \"${match.view.id}\"`,\n { type: 'dynamic-import', path: '' },\n {} as FrameworkViewConfig\n )\n }\n\n return this.loadComponent(match.frameworkConfig)\n }\n\n /**\n * Load component using the specific strategy\n */\n private async loadByStrategy(loader: ViewLoader): Promise<any> {\n switch (loader.type) {\n case 'dynamic-import':\n return this.loadDynamicImport(loader.path)\n\n case 'static-import':\n return this.loadStaticImport(loader.path)\n\n case 'custom-element':\n return this.loadCustomElement(loader.tagName)\n\n case 'registry-lookup':\n return this.loadFromRegistry(loader.registryKey)\n\n case 'custom':\n return loader.loader({} as FrameworkViewConfig) // Will be passed proper config in real usage\n\n default:\n throw new Error(`Unknown loader type: ${(loader as any).type}`)\n }\n }\n\n /**\n * Dynamic import strategy (most common)\n * Supports both static strings and lazy-loaded callbacks\n */\n private async loadDynamicImport(\n path: string | (() => Promise<any>)\n ): Promise<any> {\n // Handle callback-based lazy loading\n if (typeof path === 'function') {\n const module = await path()\n\n // Handle different export patterns\n if (module.default) {\n return module.default\n }\n\n return module\n }\n\n // Handle string-based path (static)\n const module = await import(path)\n\n // Handle different export patterns\n if (module.default) {\n return module.default\n }\n\n // If no default export, return the entire module\n return module\n }\n\n /**\n * Static import strategy (requires bundler support)\n * Supports both static strings and lazy-loaded callbacks\n */\n private async loadStaticImport(\n path: string | (() => Promise<any>)\n ): Promise<any> {\n // Handle callback-based lazy loading\n if (typeof path === 'function') {\n const module = await path()\n\n if (module.default) {\n return module.default\n }\n\n return module\n }\n\n // This would typically be handled by bundler transformation\n // For now, fall back to dynamic import\n console.warn(\n 'Static import not implemented, falling back to dynamic import'\n )\n return this.loadDynamicImport(path)\n }\n\n /**\n * Custom element strategy (for Lit components)\n */\n private async loadCustomElement(tagName: string): Promise<any> {\n // Wait for custom element to be defined\n if (typeof window !== 'undefined' && window.customElements) {\n await window.customElements.whenDefined(tagName)\n return { tagName, type: 'custom-element' }\n }\n\n throw new Error('Custom elements not available in this environment')\n }\n\n /**\n * Registry lookup strategy (for pre-registered components)\n */\n private async loadFromRegistry(registryKey: string): Promise<any> {\n // This would look up in a component registry\n // Implementation depends on framework\n throw new Error(`Registry lookup not implemented for key: ${registryKey}`)\n }\n\n /**\n * Generate cache key for component config\n */\n private getCacheKey(config: FrameworkViewConfig): string {\n const { loader, component, package: pkg } = config\n return JSON.stringify({ loader, component, package: pkg })\n }\n\n /**\n * Clear the component cache\n */\n clearCache(): void {\n this.cache.clear()\n }\n\n /**\n * Get cache statistics\n */\n getCacheStats(): { size: number; keys: string[] } {\n return {\n size: this.cache.size,\n keys: Array.from(this.cache.keys()),\n }\n }\n}\n\n/**\n * Singleton loader instance\n */\nlet globalLoader: UniversalViewLoader | null = null\n\n/**\n * Get the global view loader\n */\nexport function getGlobalLoader(): UniversalViewLoader {\n if (!globalLoader) {\n globalLoader = new UniversalViewLoader()\n }\n return globalLoader\n}\n\n/**\n * Set a custom global loader (useful for testing)\n */\nexport function setGlobalLoader(loader: UniversalViewLoader): void {\n globalLoader = loader\n}\n\n/**\n * Framework-specific helpers for strategically optimized loading patterns\n *\n * Following our Suffering Economics optimization, we support:\n * - Lit Web Components (universal web compatibility) - REQUIRED\n * - Vue (native Vue optimization) - OPTIONAL\n * - React Native (mobile-native optimization) - OPTIONAL (WebView fallback available)\n *\n * All loaders support lazy loading via callbacks:\n * ```typescript\n * // Static (bundled)\n * vueComponent('./Component.vue')\n *\n * // Lazy (loaded on demand)\n * vueComponent(() => import('./Component.vue'))\n * ```\n */\nexport const LoaderHelpers = {\n /**\n * Create a Lit custom element loader (universal web compatibility)\n */\n litComponent(tagName: string): ViewLoader {\n return { type: 'custom-element', tagName }\n },\n\n /**\n * Create a Vue component loader (native Vue, optional)\n * Supports both static paths and lazy-loaded callbacks\n */\n vueComponent(path: string | (() => Promise<any>)): ViewLoader {\n return { type: 'dynamic-import', path }\n },\n\n /**\n * Create a React Native JSX dynamic import loader (mobile-native, optional)\n * Supports both static paths and lazy-loaded callbacks\n */\n rnComponent(path: string | (() => Promise<any>)): ViewLoader {\n return { type: 'dynamic-import', path }\n },\n\n /**\n * Create a custom loader function for advanced use cases\n */\n custom(loader: (config: FrameworkViewConfig) => Promise<any>): ViewLoader {\n return { type: 'custom', loader }\n },\n\n // Legacy helpers for compilation pipelines (Vue/React → Lit)\n /**\n * @deprecated Use litComponent() instead. This exists for compilation pipeline compatibility.\n */\n vueToLitCompiled(tagName: string): ViewLoader {\n console.warn(\n 'vueToLitCompiled is deprecated. Use litComponent() - the output is the same.'\n )\n return { type: 'custom-element', tagName }\n },\n\n /**\n * @deprecated Use litComponent() instead. This exists for compilation pipeline compatibility.\n */\n reactToLitCompiled(tagName: string): ViewLoader {\n console.warn(\n 'reactToLitCompiled is deprecated. Use litComponent() - the output is the same.'\n )\n return { type: 'custom-element', tagName }\n },\n\n /**\n * @deprecated Use rnComponent() instead. Updated for better TypeScript support.\n */\n reactNativeComponent(path: string): ViewLoader {\n console.warn(\n 'reactNativeComponent is deprecated. Use rnComponent() instead.'\n )\n return { type: 'dynamic-import', path }\n },\n}\n","/**\n * TanStack Query integration for address resolution\n * Provides proper cache keys and query functions\n */\n\nimport type { ResolvedAddress } from './useAddressResolution'\nimport { resolveAddress, resolveAddresses } from './useAddressResolution'\n\n/**\n * Create TanStack Query key for address resolution\n */\nexport function getAddressQueryKey(\n address: string,\n chainId?: number\n): (string | number)[] {\n // Include chainId to ensure cache isolation per chain\n return ['address', address.toLowerCase(), chainId || 'current']\n}\n\n/**\n * Create TanStack Query key for batch address resolution\n */\nexport function getAddressesQueryKey(\n addresses: string[],\n chainId?: number\n): (string | number)[] {\n // Sort addresses for consistent cache keys\n const sortedAddresses = [...addresses]\n .map((addr) => addr.toLowerCase())\n .sort()\n return ['addresses', sortedAddresses.join(','), chainId || 'current']\n}\n\n/**\n * Query function for single address resolution\n */\nexport async function queryAddress({\n queryKey,\n}: {\n queryKey: (string | number)[]\n}): Promise<ResolvedAddress> {\n const [, address, chainIdOrCurrent] = queryKey\n const chainId =\n chainIdOrCurrent === 'current' ? undefined : (chainIdOrCurrent as number)\n\n return resolveAddress(address as string, chainId)\n}\n\n/**\n * Query function for batch address resolution\n */\nexport async function queryAddresses({\n queryKey,\n}: {\n queryKey: (string | number)[]\n}): Promise<Map<string, ResolvedAddress>> {\n const [, addressesStr, chainIdOrCurrent] = queryKey\n const chainId =\n chainIdOrCurrent === 'current' ? undefined : (chainIdOrCurrent as number)\n const addresses = (addressesStr as string).split(',')\n\n return resolveAddresses(addresses, chainId)\n}\n\n/**\n * Helper for React TanStack Query usage\n */\nexport const addressQueryOptions = {\n /**\n * Single address query options\n */\n single: (address: string, chainId?: number) => ({\n queryKey: getAddressQueryKey(address, chainId),\n queryFn: queryAddress,\n staleTime: 5 * 60 * 1000, // 5 minutes\n gcTime: 10 * 60 * 1000, // 10 minutes (formerly cacheTime)\n }),\n\n /**\n * Batch addresses query options\n */\n batch: (addresses: string[], chainId?: number) => ({\n queryKey: getAddressesQueryKey(addresses, chainId),\n queryFn: queryAddresses,\n staleTime: 5 * 60 * 1000, // 5 minutes\n gcTime: 10 * 60 * 1000, // 10 minutes\n }),\n}\n\n/**\n * Helper for Vue TanStack Query usage\n */\nexport const addressQueryOptionsVue = {\n /**\n * Single address query options for Vue Query\n */\n single: (address: string, chainId?: number) => ({\n queryKey: getAddressQueryKey(address, chainId),\n queryFn: queryAddress,\n staleTime: 5 * 60 * 1000,\n cacheTime: 10 * 60 * 1000, // Vue Query still uses cacheTime\n }),\n\n /**\n * Batch addresses query options for Vue Query\n */\n batch: (addresses: string[], chainId?: number) => ({\n queryKey: getAddressesQueryKey(addresses, chainId),\n queryFn: queryAddresses,\n staleTime: 5 * 60 * 1000,\n cacheTime: 10 * 60 * 1000,\n }),\n}\n\n/**\n * Invalidate address cache for a specific chain\n * Useful when switching chains\n */\nexport function getInvalidateAddressesPattern(\n chainId?: number\n): (string | number)[] {\n return ['address', chainId || 'current']\n}\n\n/**\n * Get all possible query keys for an address across all chains\n * Useful for invalidating cache when address profile changes\n */\nexport function getAllAddressQueryKeys(address: string): (string | number)[][] {\n return [\n ['address', address.toLowerCase(), 'current'],\n ['address', address.toLowerCase(), 42], // mainnet\n ['address', address.toLowerCase(), 4201], // testnet\n ]\n}\n","/**\n * View Events and Header Information Types\n *\n * Defines the event system for transaction views to communicate\n * with their parent containers about header display and other UI concerns.\n */\n\n/**\n * Header information that a view can provide to its parent container\n *\n * Views can emit this information to override the default header\n * that would be derived from the transaction's top-level from/to addresses.\n *\n * @example\n * ```typescript\n * // Inside a transfer view component\n * this.dispatchEvent(new CustomEvent('header-info', {\n * bubbles: true,\n * composed: true,\n * detail: {\n * from: transferFromAddress,\n * to: transferToAddress,\n * title: 'LSP7 Token Transfer'\n * }\n * }))\n * ```\n */\nexport interface TransactionHeaderInfo {\n /**\n * The \"from\" address to display in the header\n * Overrides the transaction's top-level from address\n */\n from?: string\n\n /**\n * The \"to\" address to display in the header\n * Overrides the transaction's top-level to address\n */\n to?: string\n\n /**\n * Optional title for the transaction\n * @example \"LSP7 Token Transfer\", \"Set Data\", \"Execute\"\n */\n title?: string\n\n /**\n * Optional subtitle or description\n * @example \"Send 100 tokens\", \"Update profile data\"\n */\n subtitle?: string\n\n /**\n * Optional icon identifier\n * @example \"transfer\", \"setdata\", \"execute\"\n */\n icon?: string\n\n /**\n * Optional additional metadata\n * Can be used for custom header rendering\n */\n metadata?: Record<string, any>\n}\n\n/**\n * Type-safe custom event for header information\n */\nexport interface HeaderInfoEvent extends CustomEvent {\n detail: TransactionHeaderInfo\n}\n\n/**\n * Transaction modification information\n *\n * Views emit this to modify their transaction's data (e.g., changing a parameter).\n * The view encodes its LOCAL transaction data, and the parent handles re-wrapping\n * if the transaction is inside Execute or ExecuteBatch wrappers.\n *\n * @example\n * ```typescript\n * // In a transfer view, user clicks \"Force Transfer\" checkbox\n * const newData = encodeFunctionData({\n * abi: LSP7_ABI,\n * functionName: 'transfer',\n * args: [from, to, amount, true, data] // force = true\n * })\n *\n * dispatchTransactionModification(this, {\n * data: newData,\n * transactionIndex: this.index,\n * reason: 'User enabled force transfer to EOA',\n * userInitiated: true\n * })\n * ```\n */\nexport interface TransactionModification {\n /**\n * The modified data for THIS transaction level (not wrapped)\n *\n * This is the encoded function call for the current transaction only,\n * not wrapped in Execute or Batch calls. The parent container handles re-wrapping.\n */\n data: `0x${string}`\n\n /**\n * The playback index this modification applies to\n *\n * - 0 = batch summary (modifies batch itself)\n * - 1 = first transaction (or single tx)\n * - 2 = second child transaction\n * - etc.\n *\n * This must match the `index` prop of <transaction-playback>\n */\n transactionIndex: number\n\n /**\n * Human-readable explanation of why this modification occurred\n *\n * @example \"User enabled force transfer to EOA\"\n * @example \"Slippage tolerance increased to 2%\"\n * @example \"Gas limit adjusted for complex operation\"\n */\n reason: string\n\n /**\n * Whether this modification was triggered by user interaction\n *\n * - true: User clicked checkbox, changed input, adjusted slider, etc.\n * - false: Automatic adjustment by view logic\n */\n userInitiated: boolean\n\n /**\n * Optional structured summary for quick display/logging\n */\n summary?: {\n /** Name of the field that changed */\n field: string\n\n /** Human-readable old value */\n oldValue: string\n\n /** Human-readable new value */\n newValue: string\n }\n\n /**\n * Optional validation information\n */\n validation?: {\n /** Whether the modification is valid */\n isValid: boolean\n\n /** Error message if invalid */\n error?: string\n\n /** Warning messages (modification is valid but user should be aware) */\n warnings?: string[]\n }\n}\n\n/**\n * Extended modification info added by transaction-playback\n *\n * This is what the top-level container receives after transaction-playback\n * adds context about where in the transaction tree this modification applies.\n */\nexport interface TransactionModificationWithContext\n extends TransactionModification {\n /**\n * Path from root transaction to this transaction\n *\n * @example [1] - Simple transaction at index 1\n * @example [0, 2] - Batch at index 0, child at index 2\n * @example [0, 1, 0] - Nested batch: batch[0].children[1].children[0]\n */\n transactionPath: number[]\n\n /**\n * The full local transaction object with modified data\n * (Before re-wrapping)\n */\n localTransaction: any // DecoderResult, but avoiding circular dep\n\n /**\n * Re-decoded result for verification\n * Parent should verify this decodes successfully before applying\n */\n decodedResult: any // DecoderResult\n}\n\n/**\n * Type-safe custom event for transaction modifications\n */\nexport interface TransactionModificationEvent extends CustomEvent {\n detail: TransactionModification\n}\n\n/**\n * Event type names for transaction views\n */\nexport const TransactionViewEvents = {\n /**\n * Emitted when a view wants to provide custom header information\n * Parent containers should listen for this event and update their header accordingly\n */\n HEADER_INFO: 'header-info',\n\n /**\n * Emitted when a view modifies its transaction data\n * Parent containers should listen, re-wrap if needed, and update the transaction\n */\n TRANSACTION_MODIFICATION: 'transaction-modification',\n\n /**\n * Emitted when a view's state changes (future use)\n * @example Loading state, error state, interactive state changes\n */\n STATE_CHANGE: 'view-state-change',\n\n /**\n * Emitted when a view has an action for the user (future use)\n * @example \"Approve\", \"Reject\", \"Sign\"\n */\n ACTION: 'view-action',\n} as const\n\n/**\n * Helper function to dispatch header info event\n * Use this in view components to emit header information\n *\n * @example\n * ```typescript\n * import { dispatchHeaderInfo } from '@lukso/transaction-view-headless'\n *\n * class MyTransferView extends LitElement {\n * connectedCallback() {\n * super.connectedCallback()\n * dispatchHeaderInfo(this, {\n * from: this.transferFrom,\n * to: this.transferTo,\n * title: 'Token Transfer'\n * })\n * }\n * }\n * ```\n */\nexport function dispatchHeaderInfo(\n element: HTMLElement,\n headerInfo: TransactionHeaderInfo\n): void {\n element.dispatchEvent(\n new CustomEvent(TransactionViewEvents.HEADER_INFO, {\n bubbles: true,\n composed: true, // Allows event to cross shadow DOM boundaries\n detail: headerInfo,\n })\n )\n}\n\n/**\n * Type guard to check if an event is a HeaderInfoEvent\n */\nexport function isHeaderInfoEvent(event: Event): event is HeaderInfoEvent {\n return (\n event instanceof CustomEvent &&\n event.type === TransactionViewEvents.HEADER_INFO\n )\n}\n\n/**\n * Helper function to dispatch transaction modification event\n * Use this in view components to emit transaction modifications\n *\n * @example\n * ```typescript\n * import { dispatchTransactionModification } from '@lukso/transaction-view-headless'\n *\n * class MyTransferView extends LitElement {\n * private handleForceCheckbox(checked: boolean) {\n * const newData = encodeFunctionData({\n * abi: LSP7_ABI,\n * functionName: 'transfer',\n * args: [...args, checked]\n * })\n *\n * dispatchTransactionModification(this, {\n * data: newData,\n * transactionIndex: this.index,\n * reason: 'User enabled force transfer',\n * userInitiated: true\n * })\n * }\n * }\n * ```\n */\nexport function dispatchTransactionModification(\n element: HTMLElement,\n modification: TransactionModification\n): void {\n element.dispatchEvent(\n new CustomEvent(TransactionViewEvents.TRANSACTION_MODIFICATION, {\n bubbles: true,\n composed: true,\n detail: modification,\n })\n )\n}\n\n/**\n * Type guard to check if an event is a TransactionModificationEvent\n */\nexport function isTransactionModificationEvent(\n event: Event\n): event is TransactionModificationEvent {\n return (\n event instanceof CustomEvent &&\n event.type === TransactionViewEvents.TRANSACTION_MODIFICATION\n )\n}\n"],"mappings":"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","names":["fetchMultipleAddresses","getGraphQLEndpoint","resolveAddress","module","addressCache"]}
1
+ {"version":3,"sources":["../src/config/lukso-config.ts","../src/hooks/useAddressResolution.ts","../src/index.ts","../src/composables/index.ts","../src/composables/use-image-loader.ts","../src/utils/view-matcher.ts","../src/registry/view-registry.ts","../src/composables/use-transaction-playback.ts","../src/composables/use-transaction-view.ts","../src/registry/view-loader.ts","../src/hooks/useAddressQuery.ts","../src/types/view-events.ts"],"sourcesContent":["/**\n * Framework-agnostic LUKSO configuration system\n * Works across Vue, React, and Lit components\n */\n\nimport { signal } from '@preact/signals-core'\nimport type { Chain } from 'viem'\n\nexport interface LuksoConfig {\n /** Chain ID for LUKSO network (42 for mainnet, 4201 for testnet) */\n chainId: number\n /** RPC endpoint for the LUKSO network */\n rpcUrl: string\n /** GraphQL endpoint for address resolution */\n graphqlEndpoint?: string\n /** IPFS gateway for profile images and metadata */\n ipfsGateway?: string\n /** Enable/disable address resolution */\n enableAddressResolution?: boolean\n /** Cache duration for resolved addresses (in milliseconds) */\n cacheDuration?: number\n}\n\nconst DEFAULT_CONFIG: LuksoConfig = {\n chainId: 42, // LUKSO mainnet\n rpcUrl: 'https://rpc.lukso.network',\n graphqlEndpoint: '/api/graphql', // Use local API proxy\n ipfsGateway: 'https://api.universalprofile.cloud/ipfs',\n enableAddressResolution: true,\n cacheDuration: 5 * 60 * 1000, // 5 minutes\n}\n\nlet globalConfig: LuksoConfig = { ...DEFAULT_CONFIG }\n\n/**\n * Set global LUKSO configuration\n * Call this once to configure all transaction components\n */\nexport function setLuksoConfig(config: Partial<LuksoConfig>): void {\n globalConfig = { ...globalConfig, ...config }\n\n // Clear any existing address resolution cache when config changes\n clearAddressCache()\n\n if (typeof window !== 'undefined' && window.console) {\n console.log('🌐 LUKSO Config Updated:', {\n chainId: globalConfig.chainId,\n network:\n globalConfig.chainId === 42\n ? 'mainnet'\n : globalConfig.chainId === 4201\n ? 'testnet'\n : 'custom',\n addressResolution: globalConfig.enableAddressResolution,\n })\n }\n}\n\n/**\n * Get current LUKSO configuration\n */\nexport function getLuksoConfig(): LuksoConfig {\n return { ...globalConfig }\n}\n\n/**\n * Quick helper to set mainnet configuration\n */\nexport function useLuksoMainnet(): void {\n setLuksoConfig({\n chainId: 42,\n rpcUrl: 'https://rpc.lukso.network',\n })\n}\n\n/**\n * Quick helper to set testnet configuration\n */\nexport function useLuksoTestnet(): void {\n setLuksoConfig({\n chainId: 4201,\n rpcUrl: 'https://rpc.testnet.lukso.network',\n })\n}\n\n/**\n * Address resolution cache\n */\nconst addressCache = new Map<string, any>()\nconst cacheTimestamps = new Map<string, number>()\n\nexport function cacheAddress(address: string, data: any): void {\n if (!globalConfig.enableAddressResolution) return\n\n const key = address.toLowerCase()\n addressCache.set(key, data)\n cacheTimestamps.set(key, Date.now())\n}\n\nexport function getCachedAddress(address: string): any | null {\n if (!globalConfig.enableAddressResolution) return null\n\n const key = address.toLowerCase()\n const data = addressCache.get(key)\n const timestamp = cacheTimestamps.get(key)\n\n if (!data || !timestamp) return null\n\n // Check if cache is expired\n if (\n typeof globalConfig.cacheDuration === 'number' &&\n Date.now() - timestamp > globalConfig.cacheDuration\n ) {\n addressCache.delete(key)\n cacheTimestamps.delete(key)\n return null\n }\n\n return data\n}\n\nexport function clearAddressCache(): void {\n addressCache.clear()\n cacheTimestamps.clear()\n}\n\n/**\n * Check if address resolution is enabled\n */\nexport function isAddressResolutionEnabled(): boolean {\n return globalConfig.enableAddressResolution ?? true\n}\n\n/**\n * Current chain signal for reactive chain state\n */\nexport const currentChainSignal = signal<Chain | null>(null)\n\n/**\n * Set current chain signal from viem chain object\n */\nexport function setCurrentChain(chain: Chain): void {\n currentChainSignal.value = chain\n\n // Also update the legacy global config for backwards compatibility\n setLuksoConfig({\n chainId: chain.id,\n rpcUrl: chain.rpcUrls.default.http[0],\n })\n}\n\n/**\n * Get current chain, falling back to chain derived from global config\n */\nexport function getCurrentChain(): Chain | null {\n return currentChainSignal.value\n}\n\n/**\n * Initialize chain signal from global config\n */\nexport async function initializeChainSignal(): Promise<void> {\n if (currentChainSignal.value) return\n\n try {\n const { lukso, luksoTestnet } = await import('viem/chains')\n const config = getLuksoConfig()\n\n const chain = config.chainId === 42 ? lukso : luksoTestnet\n currentChainSignal.value = chain\n } catch (error) {\n console.warn('Failed to initialize chain signal:', error)\n }\n}\n","/**\n * Framework-agnostic address resolution hook\n * Can be adapted for Vue (composable), React (hook), or Lit (controller)\n * Uses batching mechanism inspired by the decoder package\n */\n\nimport type {\n AssetData,\n EnhancedInfo,\n ProfileData,\n TokenData,\n} from '@lukso/transaction-decoder'\nimport {\n cacheAddress,\n currentChainSignal,\n getCachedAddress,\n getLuksoConfig,\n initializeChainSignal,\n isAddressResolutionEnabled,\n} from '../config/lukso-config'\n\n/**\n * Union type of all possible resolved address data\n * Combines Profile, Asset, and Token data structures\n */\nexport type ResolvedAddress = {\n address: string\n hasProfile: boolean\n truncatedAddress: string\n __gqltype?: 'Profile' | 'Asset' | 'Token' | 'Contract'\n} & Partial<ProfileData> &\n Partial<AssetData> &\n Partial<TokenData>\n\n/**\n * Truncate address to 0x{first5}...{last4} format\n */\nfunction truncateAddress(\n address: string,\n prefixLength = 5,\n suffixLength = 4\n): string {\n if (!address || address.length <= prefixLength + suffixLength + 2) {\n return address\n }\n\n const prefix = address.slice(0, 2 + prefixLength) // 0x + first 5\n const suffix = address.slice(-suffixLength) // last 4\n\n return `${prefix}...${suffix}`\n}\n\n// Per-chain batching state\ninterface ChainBatchState {\n batchTimeout: NodeJS.Timeout | null\n batchQueue: Set<string>\n batchResolvers: Map<string, (result: ResolvedAddress) => void>\n pendingResolutions: Map<string, Promise<ResolvedAddress>>\n isProcessing: boolean // Prevent concurrent batch processing\n}\n\nconst chainBatchStates = new Map<number, ChainBatchState>()\nconst BATCH_DELAY = 0 // Just wait for next tick to batch addresses from the same render cycle\nconst BATCH_SIZE = 50\n\n/**\n * Get or create batch state for a specific chain\n */\nfunction getBatchState(chainId: number): ChainBatchState {\n let state = chainBatchStates.get(chainId)\n if (!state) {\n state = {\n batchTimeout: null,\n batchQueue: new Set<string>(),\n batchResolvers: new Map<string, (result: ResolvedAddress) => void>(),\n pendingResolutions: new Map<string, Promise<ResolvedAddress>>(),\n isProcessing: false,\n }\n chainBatchStates.set(chainId, state)\n }\n return state\n}\n\n/**\n * Process a batch of addresses using decoder package's GraphQL resolver\n */\nasync function processBatch(chainId: number): Promise<void> {\n const state = getBatchState(chainId)\n if (state.batchQueue.size === 0 || state.isProcessing) return\n\n // Prevent concurrent processing for this chain\n state.isProcessing = true\n\n const addresses = Array.from(state.batchQueue)\n state.batchQueue.clear()\n\n try {\n // Use decoder package's GraphQL resolver\n const { fetchMultipleAddresses, getGraphQLEndpoint } = await import(\n '@lukso/transaction-decoder'\n )\n const { lukso, luksoTestnet } = await import('viem/chains')\n\n // Get the appropriate chain\n const chain = chainId === 42 ? lukso : luksoTestnet\n const graphqlEndpoint = getGraphQLEndpoint(chain)\n\n // Convert addresses to DataKey format expected by decoder\n const dataKeys = addresses as any[] // DataKey is a hex string type\n\n // Fetch using decoder package\n const results = await fetchMultipleAddresses(dataKeys, graphqlEndpoint)\n\n // Process results and resolve promises\n for (const address of addresses) {\n const normalizedAddress = address.toLowerCase() as any\n const enhanced: EnhancedInfo | undefined = results.get(normalizedAddress)\n\n let result: ResolvedAddress\n\n if (enhanced) {\n // Just pass through the enhanced data as-is - no need to restructure\n const profileImages = (enhanced as Record<string, any>).profileImages\n const resolvedData = {\n ...enhanced,\n hasProfile: !!(enhanced.name || profileImages?.length),\n }\n\n // Cache the result with chainId\n cacheAddressForChain(address, resolvedData, chainId)\n\n result = {\n ...resolvedData,\n address,\n truncatedAddress: truncateAddress(address),\n }\n } else {\n // No profile found\n result = {\n address,\n truncatedAddress: truncateAddress(address),\n hasProfile: false,\n }\n\n // Cache negative result with chainId\n cacheAddressForChain(address, { hasProfile: false }, chainId)\n }\n\n // Resolve the promise\n const resolver = state.batchResolvers.get(normalizedAddress)\n if (resolver) {\n resolver(result)\n state.batchResolvers.delete(normalizedAddress)\n }\n }\n } catch (error) {\n console.warn(\n 'Batch address resolution failed (falling back to API):',\n error\n )\n\n // Fallback to original API approach if decoder package fails\n try {\n const response = await fetch('/api/resolveAddresses', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n addresses,\n chainId: chainId,\n }),\n })\n\n if (!response.ok) {\n throw new Error(`API fallback failed: ${response.status}`)\n }\n\n const data = await response.json()\n\n // Process API results\n for (const address of addresses) {\n const normalizedAddress = address.toLowerCase()\n const resolved = data.resolved?.[normalizedAddress]\n\n let result: ResolvedAddress\n\n if (resolved) {\n const resolvedData = {\n name: resolved.name,\n profileImage: resolved.profileImage,\n hasProfile: !!(resolved.name || resolved.profileImage),\n }\n\n cacheAddressForChain(address, resolvedData, chainId)\n\n result = {\n address,\n truncatedAddress: truncateAddress(address),\n ...resolvedData,\n }\n } else {\n result = {\n address,\n truncatedAddress: truncateAddress(address),\n hasProfile: false,\n }\n cacheAddressForChain(address, { hasProfile: false }, chainId)\n }\n\n const resolver = state.batchResolvers.get(normalizedAddress)\n if (resolver) {\n resolver(result)\n state.batchResolvers.delete(normalizedAddress)\n }\n }\n } catch (fallbackError) {\n console.warn('Both GraphQL and API resolution failed:', fallbackError)\n\n // Return fallbacks for all addresses\n for (const address of addresses) {\n const fallback: ResolvedAddress = {\n address,\n truncatedAddress: truncateAddress(address),\n hasProfile: false,\n }\n\n cacheAddressForChain(address, { hasProfile: false }, chainId)\n\n const resolver = state.batchResolvers.get(address.toLowerCase())\n if (resolver) {\n resolver(fallback)\n state.batchResolvers.delete(address.toLowerCase())\n }\n }\n }\n } finally {\n // Always reset processing flag\n state.isProcessing = false\n }\n}\n\n/**\n * Chain-aware address cache functions\n */\nfunction cacheAddressForChain(\n address: string,\n data: any,\n chainId: number\n): void {\n const key = `${address.toLowerCase()}:${chainId}`\n cacheAddress(key, data)\n}\n\nfunction getCachedAddressForChain(\n address: string,\n chainId: number\n): any | null {\n const key = `${address.toLowerCase()}:${chainId}`\n return getCachedAddress(key)\n}\n\n/**\n * Get effective chain ID from parameter or current signal\n */\nasync function getEffectiveChainId(chainId?: number): Promise<number> {\n if (chainId !== undefined) return chainId\n\n // Initialize chain signal if needed\n await initializeChainSignal()\n\n // Get from signal or fall back to global config\n const currentChain = currentChainSignal.value\n if (currentChain) {\n return currentChain.id\n }\n\n // Final fallback to global config\n const config = getLuksoConfig()\n return config.chainId\n}\n\n/**\n * Resolve a single address using batched resolution\n * Returns immediately with cached data or fallback, then updates with resolved data\n * Handles both plain addresses and address-tokenId composite format (with - separator)\n */\nexport async function resolveAddress(\n address: string,\n chainId?: number\n): Promise<ResolvedAddress> {\n const effectiveChainId = await getEffectiveChainId(chainId)\n const normalizedAddress = address.toLowerCase()\n\n // Always provide truncated fallback using the original address\n const fallback: ResolvedAddress = {\n address,\n truncatedAddress: truncateAddress(address),\n hasProfile: false,\n }\n\n // Return fallback immediately if resolution disabled\n if (!isAddressResolutionEnabled()) {\n return fallback\n }\n\n // Check cache first (chain-aware)\n const cached = getCachedAddressForChain(address, effectiveChainId)\n if (cached) {\n return {\n ...fallback,\n ...cached,\n hasProfile: !!(cached.name || cached.profileImage),\n }\n }\n\n const state = getBatchState(effectiveChainId)\n\n // Check if resolution is already pending for this chain\n const existingPromise = state.pendingResolutions.get(normalizedAddress)\n if (existingPromise) {\n return existingPromise\n }\n\n // Safety check: if we already have this address in the batch queue, return a fast fallback\n if (state.batchQueue.has(normalizedAddress)) {\n return Promise.resolve(fallback)\n }\n\n // Create new resolution promise\n const resolutionPromise = new Promise<ResolvedAddress>((resolve) => {\n // Add full address to batch queue (supports address-tokenId format with -)\n state.batchQueue.add(normalizedAddress)\n state.batchResolvers.set(normalizedAddress, resolve)\n\n // Clear existing timeout\n if (state.batchTimeout) {\n clearTimeout(state.batchTimeout)\n }\n\n // Set new timeout for batch processing (only if not already processing)\n if (!state.isProcessing) {\n state.batchTimeout = setTimeout(() => {\n state.batchTimeout = null\n processBatch(effectiveChainId)\n }, BATCH_DELAY)\n\n // Process immediately if batch is full\n if (state.batchQueue.size >= BATCH_SIZE) {\n if (state.batchTimeout) {\n clearTimeout(state.batchTimeout)\n state.batchTimeout = null\n }\n processBatch(effectiveChainId)\n }\n }\n })\n\n // Store the promise to avoid duplicate requests\n state.pendingResolutions.set(normalizedAddress, resolutionPromise)\n\n // Clean up after resolution\n resolutionPromise.finally(() => {\n state.pendingResolutions.delete(normalizedAddress)\n })\n\n return resolutionPromise\n}\n\n/**\n * Resolve multiple addresses\n */\nexport async function resolveAddresses(\n addresses: string[],\n chainId?: number\n): Promise<Map<string, ResolvedAddress>> {\n const results = new Map<string, ResolvedAddress>()\n\n // Resolve all addresses in parallel using the batched resolver\n const resolutionPromises = addresses.map(async (address) => {\n const resolved = await resolveAddress(address, chainId)\n results.set(address.toLowerCase(), resolved)\n })\n\n await Promise.all(resolutionPromises)\n return results\n}\n\n/**\n * Simple reactive state for frameworks to implement\n * Each framework will wrap this with their reactivity system\n */\nexport interface AddressResolutionState {\n resolved: ResolvedAddress | null\n loading: boolean\n error: string | null\n}\n\n/**\n * Create initial state\n */\nexport function createAddressResolutionState(): AddressResolutionState {\n return {\n resolved: null,\n loading: false,\n error: null,\n }\n}\n\n/**\n * Framework-agnostic resolution function that updates state\n */\nexport async function resolveAddressWithState(\n address: string,\n _state: AddressResolutionState,\n updateCallback: (newState: Partial<AddressResolutionState>) => void,\n chainId?: number\n): Promise<void> {\n // Start loading\n updateCallback({ loading: true, error: null })\n\n try {\n const resolved = await resolveAddress(address, chainId)\n updateCallback({\n resolved,\n loading: false,\n error: null,\n })\n } catch (error) {\n updateCallback({\n loading: false,\n error: error instanceof Error ? error.message : 'Resolution failed',\n })\n }\n}\n","// Main exports for the decoder-headless package\n\nexport type {\n AddressImageData,\n AddressResolutionState,\n ImageLoadOptions,\n ImageResult,\n LuksoConfig,\n ResolvedAddress,\n UseTransactionViewOptions,\n UseTransactionViewResult,\n} from './composables'\nexport * from './composables'\nexport {\n findBestTransactionView,\n useTransactionView,\n} from './composables'\n// Configuration and address resolution (framework-agnostic)\nexport * from './config/lukso-config'\nexport * from './hooks/useAddressQuery'\nexport * from './hooks/useAddressResolution'\nexport * from './registry'\n// Convenience re-exports for common use cases\nexport {\n getGlobalLoader,\n getGlobalRegistry,\n} from './registry'\nexport type {\n DecoderRecordForSelection,\n ViewContext,\n ViewDefinition,\n ViewMatch,\n ViewMatchCriteria,\n} from './types'\nexport * from './types'\nexport * from './utils'\n// Release update\n// build 2\n","// Configuration exports\nexport type { LuksoConfig } from '../config/lukso-config'\nexport {\n cacheAddress,\n clearAddressCache,\n getCachedAddress,\n getLuksoConfig,\n isAddressResolutionEnabled,\n setLuksoConfig,\n useLuksoMainnet,\n useLuksoTestnet,\n} from '../config/lukso-config'\n// Address resolution exports\nexport type {\n AddressResolutionState,\n ResolvedAddress,\n} from '../hooks/useAddressResolution'\nexport {\n createAddressResolutionState,\n resolveAddress,\n resolveAddresses,\n resolveAddressWithState,\n} from '../hooks/useAddressResolution'\nexport type {\n ViewContext,\n ViewContextRequirements,\n ViewVariant,\n} from '../types/view-contexts'\nexport type { ViewMatch } from '../types/view-matching'\nexport type {\n AddressImageData,\n ImageLoadOptions,\n ImageResult,\n} from './use-image-loader'\nexport {\n useAddressResolver,\n useImageLoader,\n} from './use-image-loader'\n// Transaction playback exports\nexport type {\n PlaybackIndexResult,\n TransactionPlaybackOptions,\n TransactionPlaybackState,\n} from './use-transaction-playback'\nexport {\n createTransactionPlayback,\n getValidPlaybackIndices,\n isValidPlaybackIndex,\n useTransactionPlayback,\n} from './use-transaction-playback'\nexport type {\n UseTransactionViewOptions,\n UseTransactionViewResult,\n} from './use-transaction-view'\nexport {\n findAllTransactionViews,\n findBestTransactionView,\n useTransactionView,\n} from './use-transaction-view'\n","import type { ImageData } from '@lukso/transaction-decoder'\n\n// Force cache invalidation\nconsole.log(\n '🔥 LOADING NEW useAddressResolver CODE - should see GraphQL integration'\n)\n\n/**\n * Image loading configuration for different contexts\n */\nexport interface ImageLoadOptions {\n width?: number\n height?: number\n dpr?: number\n index?: number\n}\n\n/**\n * Resolved image result\n */\nexport interface ImageResult {\n src: string\n width?: number\n height?: number\n}\n\n/**\n * Address/Profile data structure for image resolution\n * Note: GraphQL pluralizes field names (icons, not icon)\n */\nexport interface AddressImageData {\n profileImages?: ImageData[]\n avatar?: ImageData[]\n icons?: ImageData[] // GraphQL pluralizes to \"icons\"\n images?: ImageData[]\n __gqltype?: string\n}\n\n// Image loading cache for preventing duplicate requests\nconst imageLoadCache = new Map<string, Promise<ImageResult | null>>()\n\n/**\n * Generate cache key for image loading based on image data and options\n */\nfunction getImageCacheKey(imageData: any[], options: ImageLoadOptions): string {\n // Create a stable key based on the image data sources and size requirements\n const imageUrls = imageData\n .filter((img) => img?.url || img?.src)\n .map((img) => img.url || img.src)\n .sort()\n .join(',')\n\n const sizeKey = `${options.width || 32}x${options.height || options.width || 32}@${options.dpr || 1}`\n\n return `${imageUrls}-${sizeKey}`\n}\n\n/**\n * Composable for loading images from various sources\n * Extracted from Vue AddressView component for framework-agnostic use\n */\nexport function useImageLoader() {\n /**\n * Load image from GraphQL-resolved image groups using proper size selection\n */\n async function loadImage(\n imageData: any[],\n options: ImageLoadOptions = {}\n ): Promise<ImageResult | null> {\n try {\n if (!imageData || imageData.length === 0) {\n return null\n }\n\n // Default options\n const loadOptions = {\n width: options.width || 32,\n height: options.height || options.width || 32,\n dpr:\n options.dpr ||\n (typeof window !== 'undefined' ? window.devicePixelRatio : 1),\n ignoreHead: true, // Skip HEAD requests in component context\n }\n\n // Check cache first to prevent duplicate requests\n const cacheKey = getImageCacheKey(imageData, loadOptions)\n const cachedPromise = imageLoadCache.get(cacheKey)\n if (cachedPromise) {\n console.log('📸 loadImage: Using cached promise for', cacheKey)\n return cachedPromise\n }\n\n console.log(\n '📸 loadImage: Creating new request for',\n imageData.length,\n 'options:',\n loadOptions\n )\n\n // Create and cache the loading promise\n const loadingPromise = (async (): Promise<ImageResult | null> => {\n // Import the proper getImage function from decoder package\n const { getImage } = await import('@lukso/transaction-decoder')\n\n const result = await getImage(imageData, loadOptions)\n\n if (result?.src) {\n console.log('📸 loadImage: Selected image:', result.src)\n return {\n src: result.src,\n width: result.width,\n height: result.height,\n }\n }\n\n return null\n })()\n\n // Cache the promise\n imageLoadCache.set(cacheKey, loadingPromise)\n\n // Clean up cache on completion (success or failure)\n loadingPromise.finally(() => {\n // Keep successful results cached, remove failures\n loadingPromise\n .then((result) => {\n if (!result) {\n imageLoadCache.delete(cacheKey)\n }\n })\n .catch(() => {\n imageLoadCache.delete(cacheKey)\n })\n })\n\n return loadingPromise\n } catch (error) {\n console.warn('Failed to load image:', error)\n return null\n }\n }\n\n /**\n * Get profile/avatar image from address data\n * Priority differs based on type:\n * - Profiles: profileImages first\n * - NFTs/Contracts: icons first (GraphQL pluralizes to \"icons\"), then images\n * - Avatars are from other contracts (not used yet)\n */\n async function loadProfileImage(\n addressData: AddressImageData,\n options: ImageLoadOptions = {}\n ): Promise<ImageResult | null> {\n // For Profiles, prioritize profileImages\n if (addressData.__gqltype === 'Profile') {\n // Try profileImages first\n if (addressData.profileImages?.length) {\n const result = await loadImage(addressData.profileImages, options)\n if (result) return result\n }\n // Fallback to icons\n if (addressData.icons?.length) {\n const result = await loadImage(addressData.icons, options)\n if (result) return result\n }\n // Fallback to images\n if (addressData.images?.length) {\n return loadImage(addressData.images, options)\n }\n return null\n }\n\n // For NFTs/Contracts, prioritize icons, fallback to images\n // Tokens/Assets will never have profileImages, so only check icons and images\n // Try icons first\n if (addressData.icons?.length) {\n const result = await loadImage(addressData.icons, options)\n if (result) return result\n }\n // Fallback to images\n if (addressData.images?.length) {\n return loadImage(addressData.images, options)\n }\n\n return null\n }\n\n /**\n * Load background image from resolved address data\n */\n async function loadBackgroundImage(\n addressData: AddressImageData & { backgroundImages?: any[] },\n options: ImageLoadOptions = {}\n ): Promise<ImageResult | null> {\n const imageGroup = addressData.backgroundImages || []\n return loadImage(imageGroup, options)\n }\n\n /**\n * Get fallback image based on address type\n */\n function getFallbackImage(addressData: AddressImageData): ImageResult {\n const isProfile = addressData.__gqltype === 'Profile'\n return {\n src: isProfile\n ? '/assets/images/profile-default.svg'\n : '/assets/images/token-default.svg',\n }\n }\n\n /**\n * Determine if address represents a contract (has square icon)\n */\n function isContractAddress(addressData: AddressImageData): boolean {\n return addressData.__gqltype !== 'Profile'\n }\n\n return {\n loadImage,\n loadProfileImage,\n loadBackgroundImage,\n getFallbackImage,\n isContractAddress,\n }\n}\n\n/**\n * Composable for address resolution and formatting\n * Connected to decoder package's GraphQL AddressResolver\n */\nexport function useAddressResolver() {\n /**\n * Resolve address data using decoder package integration\n * Uses the batched address resolution from useAddressResolution\n */\n async function resolveAddress(address: string): Promise<any> {\n console.log('🔥 useAddressResolver.resolveAddress called with:', address)\n\n try {\n // Import and use the batched resolution from the hooks\n const { resolveAddress: batchedResolve } = await import(\n '../hooks/useAddressResolution'\n )\n\n console.log('🔥 useAddressResolver: calling batchedResolve...')\n const resolved = await batchedResolve(address)\n console.log('🔥 useAddressResolver: batchedResolve returned:', resolved)\n\n // Always return something, even if no profile - this ensures we don't return null unnecessarily\n const result = {\n // Preserve all image arrays from GraphQL\n ...resolved,\n // Override with computed values only if not already set by GraphQL\n address: resolved.address,\n name: resolved.name || '',\n __gqltype:\n resolved.__gqltype || (resolved.hasProfile ? 'Profile' : 'Contract'),\n }\n\n console.log('🔥 useAddressResolver: returning result:', result)\n return result\n } catch (error) {\n console.error('🔥 useAddressResolver: Failed to resolve address:', error)\n\n // Return a fallback instead of null\n return {\n address,\n name: '',\n __gqltype: 'Contract',\n profileImages: [],\n avatar: [],\n icon: [],\n }\n }\n }\n\n /**\n * Format address display name from resolved data\n */\n function formatDisplayName(addressData: any): string {\n const baseName =\n addressData.name?.toLowerCase?.() ||\n addressData.lsp4TokenName ||\n addressData.baseAsset?.lsp4TokenName ||\n ''\n\n const symbol =\n addressData.lsp4TokenSymbol ||\n addressData.baseAsset?.lsp4TokenSymbol ||\n ''\n\n return symbol ? `${baseName} (${symbol})` : baseName\n }\n\n /**\n * Get address prefix based on type\n */\n function getAddressPrefix(addressData: any): string {\n return addressData.__gqltype !== 'Profile' ? '🪙 ' : '@'\n }\n\n /**\n * Check if address should show name colors\n */\n function shouldShowNameColor(addressData: any): boolean {\n return addressData.__gqltype === 'Profile'\n }\n\n return {\n resolveAddress,\n formatDisplayName,\n getAddressPrefix,\n shouldShowNameColor,\n }\n}\n","import type { DecoderResult } from '@lukso/transaction-decoder'\nimport type {\n DecoderRecordForSelection,\n ViewDefinition,\n ViewMatch,\n ViewMatchCriteria,\n ViewMatchOptions,\n} from '../types/view-matching'\n\n/**\n * Weights for different matching criteria (higher = more important)\n * Context is optional - only weighted when both view and request specify context\n */\nexport const CRITERIA_WEIGHTS = {\n recordType: 0.25, // Most specific to transaction type\n functionName: 0.2, // Function-level specificity\n context: 0.2, // Context specificity (when opt-in)\n standard: 0.15, // LSP standard specificity\n contractAddress: 0.1, // Contract-specific logic\n contextRequirements: 0.05, // Context requirement matching\n chainId: 0.03, // Network-specific behavior\n customMatcher: 0.02, // Custom logic (lowest weight due to unpredictability)\n} as const\n\n/**\n * Calculate how well a view matches a transaction and context\n *\n * Context matching is opt-in:\n * - If view specifies context criteria, request MUST provide matching context\n * - If view has no context criteria, it matches any context (universal view)\n * - If request has no context, context-specific views are deprioritized\n *\n * Note: For batch operations (executeBatch, setDataBatch, etc.), this matches\n * against the parent transaction. Future enhancement could include matching\n * against child transactions for more granular view selection.\n */\nexport function calculateMatchScore(\n transaction: DecoderResult,\n view: ViewDefinition,\n options?: Pick<ViewMatchOptions, 'context' | 'contextRequirements'>\n): { score: number; matchedCriteria: (keyof ViewMatchCriteria)[] } {\n const { criteria } = view\n const matchedCriteria: (keyof ViewMatchCriteria)[] = []\n let totalWeight = 0\n let matchedWeight = 0\n\n // Check each criterion and accumulate scores\n for (const [criterion, weight] of Object.entries(CRITERIA_WEIGHTS)) {\n const criterionKey = criterion as keyof ViewMatchCriteria\n const criterionValue = criteria[criterionKey]\n\n if (criterionValue === undefined) continue\n\n totalWeight += weight\n\n // Special handling for customMatcher - use match count\n if (\n criterionKey === 'customMatcher' &&\n typeof criterionValue === 'function'\n ) {\n try {\n const matchCount = criterionValue(transaction)\n if (matchCount > 0) {\n matchedCriteria.push(criterionKey)\n // Normalize match count to 0-1 range (cap at 10 conditions)\n const normalizedScore = Math.min(matchCount / 10, 1)\n matchedWeight += weight * normalizedScore\n }\n } catch (error) {\n console.warn('Custom matcher threw error:', error)\n }\n continue\n }\n\n if (\n doesCriterionMatch(transaction, criterionKey, criterionValue, options)\n ) {\n matchedCriteria.push(criterionKey)\n matchedWeight += weight\n }\n }\n\n // Handle context opt-in logic\n const viewHasContext = criteria.context !== undefined\n const requestHasContext = options?.context !== undefined\n\n if (viewHasContext && !requestHasContext) {\n // View requires specific context, but none provided - penalize heavily\n matchedWeight *= 0.1 // Reduce score by 90%\n } else if (!viewHasContext && requestHasContext) {\n // Universal view matching specific context - slight penalty to prefer context-specific views\n matchedWeight *= 0.9 // Reduce score by 10%\n }\n\n // If no criteria are defined, this view doesn't match\n if (totalWeight === 0) return { score: 0, matchedCriteria: [] }\n\n // Calculate final score (0-1)\n const score = matchedWeight / totalWeight\n\n return { score, matchedCriteria }\n}\n\n/**\n * Check if a specific criterion matches the transaction\n */\nfunction doesCriterionMatch(\n transaction: DecoderResult,\n criterion: keyof ViewMatchCriteria,\n criterionValue: any,\n options?: Pick<ViewMatchOptions, 'context' | 'contextRequirements'>\n): boolean {\n switch (criterion) {\n case 'recordType':\n return matchesStringOrArray(\n (transaction as DecoderRecordForSelection).recordType,\n criterionValue\n )\n\n case 'functionName':\n return matchesStringOrArray(\n (transaction as DecoderRecordForSelection).functionName,\n criterionValue\n )\n\n case 'standard':\n return matchesStringOrArray(\n (transaction as DecoderRecordForSelection).standard,\n criterionValue\n )\n\n case 'contractAddress':\n return matchesStringOrArray(\n (transaction as DecoderRecordForSelection).contractAddress,\n criterionValue\n )\n\n case 'chainId':\n return matchesNumberOrArray(transaction.chainId, criterionValue)\n\n case 'context':\n if (!options?.context) return false // No context provided, can't match\n return matchesStringOrArray(options.context, criterionValue)\n\n case 'contextRequirements':\n if (!options?.contextRequirements || !criterionValue) return false\n return areContextRequirementsCompatible(\n options.contextRequirements,\n criterionValue\n )\n\n case 'customMatcher':\n if (typeof criterionValue === 'function') {\n try {\n const matchCount = criterionValue(transaction)\n // Match if any conditions matched (> 0)\n // The actual count contributes to the score in calculateMatchScore\n return matchCount > 0\n } catch (error) {\n console.warn('Custom matcher threw error:', error)\n return false\n }\n }\n return false\n\n default:\n return false\n }\n}\n\n/**\n * Helper to match string values against string or array criteria\n */\nfunction matchesStringOrArray(\n value: string | undefined,\n criteria: string | string[]\n): boolean {\n if (!value || !criteria) return false\n\n if (Array.isArray(criteria)) {\n return criteria.includes(value)\n }\n\n return value === criteria\n}\n\n/**\n * Helper to match number values against number or array criteria\n */\nfunction matchesNumberOrArray(\n value: number | undefined,\n criteria: number | number[]\n): boolean {\n if (value === undefined || criteria === undefined) return false\n\n if (Array.isArray(criteria)) {\n return criteria.includes(value)\n }\n\n return value === criteria\n}\n\n/**\n * Check if context requirements are compatible\n */\nfunction areContextRequirementsCompatible(\n requested: any,\n viewRequirements: any\n): boolean {\n // Simple compatibility check - can be extended\n if (requested.detailLevel && viewRequirements.detailLevel) {\n const detailOrder = ['minimal', 'summary', 'full', 'debug']\n const requestedLevel = detailOrder.indexOf(requested.detailLevel)\n const viewLevel = detailOrder.indexOf(viewRequirements.detailLevel)\n if (viewLevel < requestedLevel) return false\n }\n\n if (requested.maxHeight && viewRequirements.maxHeight) {\n if (viewRequirements.maxHeight > requested.maxHeight) return false\n }\n\n return true\n}\n\n/**\n * Calculate native framework priority bonus\n *\n * Native framework implementations (Vue, React Native) get priority over Lit fallbacks:\n * - Vue: +0.15 bonus when view has Vue implementation\n * - React Native (rn): +0.15 bonus when view has RN implementation\n * - Lit: NO bonus (Lit is the universal fallback)\n *\n * This ensures that when both native and Lit views exist for the same transaction:\n * - Vue app prefers Vue view (Vue score + 0.15 > Lit score)\n * - React Native app prefers RN view (RN score + 0.15 > Lit score)\n * - Other frameworks use Lit view (universal compatibility)\n */\nfunction calculateNativeFrameworkBonus(\n view: ViewDefinition,\n requestedFramework: 'lit' | 'vue' | 'rn'\n): number {\n // Lit gets no bonus - it's the universal fallback\n if (requestedFramework === 'lit') {\n return 0\n }\n\n // Vue gets bonus if view has Vue implementation\n if (requestedFramework === 'vue' && view.frameworks.vue) {\n return 0.15\n }\n\n // React Native gets bonus if view has RN implementation\n if (requestedFramework === 'rn' && view.frameworks.rn) {\n return 0.15\n }\n\n return 0\n}\n\n/**\n * Find and score all matching views for a transaction\n *\n * Views are matched and sorted by:\n * 1. Match score (how well criteria match the transaction)\n * 2. Native framework bonus (Vue/RN get +0.15, Lit gets 0)\n * 3. View priority (manually set priority)\n *\n * This ensures that native framework views are preferred when available,\n * while Lit serves as a universal fallback.\n */\nexport function findMatchingViews(\n transaction: DecoderResult,\n views: ViewDefinition[],\n options: ViewMatchOptions\n): ViewMatch[] {\n const matches: ViewMatch[] = []\n const minScore = options.minScore ?? 0\n\n for (const view of views) {\n // Skip if framework is not supported\n if (!view.frameworks[options.framework]) {\n continue\n }\n\n const { score, matchedCriteria } = calculateMatchScore(transaction, view, {\n context: options.context,\n contextRequirements: options.contextRequirements,\n })\n\n // Skip if score is below threshold\n if (score < minScore) {\n continue\n }\n\n // Apply native framework bonus (Vue/RN only, NOT Lit)\n const frameworkBonus = calculateNativeFrameworkBonus(\n view,\n options.framework\n )\n const finalScore = Math.min(1, score + frameworkBonus)\n\n const match: ViewMatch = {\n view,\n score: finalScore,\n matchedCriteria,\n frameworkConfig: options.includeFrameworkConfig\n ? view.frameworks[options.framework]\n : undefined,\n }\n\n matches.push(match)\n }\n\n // Sort by score (descending), then by priority (descending)\n matches.sort((a, b) => {\n if (a.score !== b.score) {\n return b.score - a.score\n }\n return b.view.priority - a.view.priority\n })\n\n // Limit results if requested\n if (options.maxMatches) {\n return matches.slice(0, options.maxMatches)\n }\n\n return matches\n}\n\n/**\n * TODO: Future enhancement for batch operations\n *\n * For batch operations like executeBatch, setDataBatch, we might want to:\n * 1. Match against the batch container (current behavior)\n * 2. Also match against child transactions for more specific views\n * 3. Allow views to specify whether they handle batches vs individual items\n * 4. Support composite views that render both batch info + child items\n */\n","import type { DecoderResult } from '@lukso/transaction-decoder'\nimport type {\n ViewDefinition,\n ViewMatch,\n ViewMatchOptions,\n ViewRegistry,\n} from '../types/view-matching'\nimport { findMatchingViews } from '../utils/view-matcher'\n\n/**\n * Default view registry implementation\n */\nexport class DefaultViewRegistry implements ViewRegistry {\n private views = new Map<string, ViewDefinition>()\n\n register(view: ViewDefinition): void {\n if (this.views.has(view.id)) {\n console.warn(\n `View with id \"${view.id}\" is already registered. Overwriting.`\n )\n }\n\n this.views.set(view.id, view)\n }\n\n unregister(viewId: string): void {\n this.views.delete(viewId)\n }\n\n getAllViews(): ViewDefinition[] {\n return Array.from(this.views.values())\n }\n\n findMatches(\n transaction: DecoderResult,\n options: ViewMatchOptions\n ): ViewMatch[] {\n const allViews = this.getAllViews()\n return findMatchingViews(transaction, allViews, options)\n }\n\n getView(viewId: string): ViewDefinition | undefined {\n return this.views.get(viewId)\n }\n\n clear(): void {\n this.views.clear()\n }\n\n /**\n * Get the best matching view (highest score) for a transaction\n */\n getBestMatch(\n transaction: DecoderResult,\n options: ViewMatchOptions\n ): ViewMatch | null {\n const matches = this.findMatches(transaction, { ...options, maxMatches: 1 })\n return matches[0] || null\n }\n\n /**\n * Bulk register multiple views\n */\n registerMany(views: ViewDefinition[]): void {\n for (const view of views) {\n this.register(view)\n }\n }\n\n /**\n * Get stats about registered views\n */\n getStats(): {\n totalViews: number\n viewsByFramework: Record<string, number>\n viewsByRecordType: Record<string, number>\n } {\n const allViews = this.getAllViews()\n const totalViews = allViews.length\n\n const viewsByFramework: Record<string, number> = {}\n const viewsByRecordType: Record<string, number> = {}\n\n for (const view of allViews) {\n // Count framework support\n for (const framework of Object.keys(view.frameworks)) {\n viewsByFramework[framework] = (viewsByFramework[framework] || 0) + 1\n }\n\n // Count by record type\n const recordType = view.criteria.recordType\n if (recordType) {\n const types = Array.isArray(recordType) ? recordType : [recordType]\n for (const type of types) {\n viewsByRecordType[type] = (viewsByRecordType[type] || 0) + 1\n }\n }\n }\n\n return {\n totalViews,\n viewsByFramework,\n viewsByRecordType,\n }\n }\n}\n\n/**\n * Global registry instance\n */\nlet globalRegistry: ViewRegistry | null = null\n\n/**\n * Get or create the global view registry\n */\nexport function getGlobalRegistry(): ViewRegistry {\n if (!globalRegistry) {\n globalRegistry = new DefaultViewRegistry()\n }\n return globalRegistry\n}\n\n/**\n * Set a custom global registry (useful for testing or custom implementations)\n */\nexport function setGlobalRegistry(registry: ViewRegistry): void {\n globalRegistry = registry\n}\n\n/**\n * Reset the global registry (mainly for testing)\n */\nexport function resetGlobalRegistry(): void {\n globalRegistry = null\n}\n","import type { DecoderResult } from '@lukso/transaction-decoder'\nimport type { Chain } from 'viem'\nimport { getGlobalRegistry } from '../registry/view-registry'\nimport type {\n ViewMatch,\n ViewMatchOptions,\n ViewRegistry,\n} from '../types/view-matching'\n\n/**\n * Transaction Playback System\n *\n * Provides index-based access to transaction views with smart handling of batches:\n *\n * **Single Transaction:**\n * - Index 0: The transaction itself\n * - Index 1: The transaction itself (same as 0)\n * - Index 2+: null\n *\n * **Batch Transaction (setDataBatch, executeBatch):**\n * - Index 0: Summary/expandable view of the batch\n * - Index 1: First child transaction\n * - Index 2: Second child transaction\n * - Index N: Nth child transaction\n *\n * This design allows UI flexibility:\n * - Always use index 1 to skip batch summaries\n * - Use index 0 to show batch overview (optional)\n * - Navigate batch children by index\n */\n\n/**\n * Options for transaction playback\n */\nexport interface TransactionPlaybackOptions extends Partial<ViewMatchOptions> {\n /** Custom registry to use instead of global */\n registry?: ViewRegistry\n /** Fallback view ID if no matches found */\n fallbackViewId?: string\n /** Chain for address resolution */\n chain?: Chain\n}\n\n/**\n * Result of selecting a view at a specific index\n */\nexport interface PlaybackIndexResult {\n /** The selected view match (or null if invalid index) */\n match: ViewMatch | null\n /** The transaction data for this index */\n transaction: DecoderResult | null\n /** Index information */\n indexInfo: {\n /** Requested index */\n requested: number\n /** Actual index in children array (for batches) */\n childIndex: number | null\n /** Whether this is a batch summary view (index 0 of batch) */\n isBatchSummary: boolean\n /** Whether this is a valid index */\n isValid: boolean\n }\n /** Batch information (if applicable) */\n batchInfo: {\n /** Whether the root transaction is a batch */\n isBatch: boolean\n /** Total number of children in batch (0 if not batch) */\n childCount: number\n /** Available indices (e.g., [0, 1, 2, 3] for 3-child batch) */\n availableIndices: number[]\n }\n}\n\n/**\n * Complete playback state for a transaction\n */\nexport interface TransactionPlaybackState {\n /** The root transaction */\n rootTransaction: DecoderResult\n /** Whether this is a batch transaction */\n isBatch: boolean\n /** Child transactions (empty if not batch) */\n children: DecoderResult[]\n /** Total count of available indices */\n indexCount: number\n /** Batch information */\n batchInfo: {\n /** Whether the root transaction is a batch */\n isBatch: boolean\n /** Total number of children in batch (0 if not batch) */\n childCount: number\n /** Available indices (e.g., [0, 1, 2, 3] for 3-child batch) */\n availableIndices: number[]\n }\n /** Get view match for a specific index */\n getViewAtIndex: (index: number) => PlaybackIndexResult\n /** Get all available views */\n getAllViews: () => PlaybackIndexResult[]\n}\n\n/**\n * Check if a transaction is a batch transaction\n *\n * Only executeBatch is a navigable batch where:\n * - Index 0 shows batch summary\n * - Index 1+ shows individual child transactions\n *\n * setDataBatch is NOT a batch - it's a single transaction with a special view\n * that renders all key/value pairs from children.\n */\nfunction isBatchTransaction(transaction: DecoderResult): boolean {\n return transaction.resultType === 'executeBatch'\n}\n\n/**\n * Get children from a batch transaction\n */\nfunction getBatchChildren(transaction: DecoderResult): DecoderResult[] {\n if (!isBatchTransaction(transaction)) {\n return []\n }\n return (transaction as any).children || []\n}\n\n/**\n * Core function to select view at a specific index\n */\nfunction selectViewAtIndex(\n rootTransaction: DecoderResult,\n index: number,\n options: TransactionPlaybackOptions\n): PlaybackIndexResult {\n const {\n registry = getGlobalRegistry(),\n framework = 'lit',\n fallbackViewId,\n minScore = 0,\n includeFrameworkConfig = true,\n } = options\n\n const isBatch = isBatchTransaction(rootTransaction)\n const children = getBatchChildren(rootTransaction)\n const childCount = children.length\n\n // Initialize result\n const result: PlaybackIndexResult = {\n match: null,\n transaction: null,\n indexInfo: {\n requested: index,\n childIndex: null,\n isBatchSummary: false,\n isValid: false,\n },\n batchInfo: {\n isBatch,\n childCount,\n availableIndices: [],\n },\n }\n\n // Calculate available indices\n if (isBatch) {\n // Batch: 0 (summary) + N children\n result.batchInfo.availableIndices = Array.from(\n { length: childCount + 1 },\n (_, i) => i\n )\n } else {\n // Single: 0 and 1 both map to the transaction\n result.batchInfo.availableIndices = [0, 1]\n }\n\n // Validate index\n if (index < 0) {\n return result // Invalid: negative index\n }\n\n // Handle single transaction\n if (!isBatch) {\n if (index === 0 || index === 1) {\n result.indexInfo.isValid = true\n result.transaction = rootTransaction\n\n // Find matching view for the transaction\n const matchOptions: ViewMatchOptions = {\n framework: framework as any,\n minScore,\n maxMatches: 1,\n includeFrameworkConfig,\n }\n\n const matches = registry.findMatches(rootTransaction, matchOptions)\n result.match = matches[0] || null\n\n // Try fallback if no match\n if (!result.match && fallbackViewId) {\n const fallbackView = registry.getView(fallbackViewId)\n if (fallbackView?.frameworks[framework]) {\n result.match = {\n view: fallbackView,\n score: 0,\n matchedCriteria: [],\n frameworkConfig: includeFrameworkConfig\n ? fallbackView.frameworks[framework]\n : undefined,\n }\n }\n }\n\n return result\n }\n\n // Invalid index for single transaction\n return result\n }\n\n // Handle batch transaction\n if (index === 0) {\n // Index 0: Batch summary view\n result.indexInfo.isValid = true\n result.indexInfo.isBatchSummary = true\n result.transaction = rootTransaction\n\n // Find batch summary view\n const matchOptions: ViewMatchOptions = {\n framework: framework as any,\n minScore,\n maxMatches: 1,\n includeFrameworkConfig,\n }\n\n const matches = registry.findMatches(rootTransaction, matchOptions)\n result.match = matches[0] || null\n\n // Try fallback if no match\n if (!result.match && fallbackViewId) {\n const fallbackView = registry.getView(fallbackViewId)\n if (fallbackView?.frameworks[framework]) {\n result.match = {\n view: fallbackView,\n score: 0,\n matchedCriteria: [],\n frameworkConfig: includeFrameworkConfig\n ? fallbackView.frameworks[framework]\n : undefined,\n }\n }\n }\n\n return result\n }\n\n // Index 1+: Child transactions\n const childIndex = index - 1\n if (childIndex >= 0 && childIndex < childCount) {\n result.indexInfo.isValid = true\n result.indexInfo.childIndex = childIndex\n result.transaction = children[childIndex]\n\n // Find matching view for the child transaction\n const matchOptions: ViewMatchOptions = {\n framework: framework as any,\n minScore,\n maxMatches: 1,\n includeFrameworkConfig,\n }\n\n const matches = registry.findMatches(result.transaction, matchOptions)\n result.match = matches[0] || null\n\n // Try fallback if no match\n if (!result.match && fallbackViewId) {\n const fallbackView = registry.getView(fallbackViewId)\n if (fallbackView?.frameworks[framework]) {\n result.match = {\n view: fallbackView,\n score: 0,\n matchedCriteria: [],\n frameworkConfig: includeFrameworkConfig\n ? fallbackView.frameworks[framework]\n : undefined,\n }\n }\n }\n\n return result\n }\n\n // Invalid index for batch\n return result\n}\n\n/**\n * Create a playback state for a transaction\n *\n * @example\n * ```typescript\n * const playback = createTransactionPlayback(transaction, { framework: 'lit' })\n *\n * // For single transaction:\n * playback.getViewAtIndex(0) // Returns the transaction\n * playback.getViewAtIndex(1) // Returns the transaction (same)\n * playback.getViewAtIndex(2) // Returns null (invalid)\n *\n * // For batch transaction:\n * playback.getViewAtIndex(0) // Returns batch summary\n * playback.getViewAtIndex(1) // Returns first child\n * playback.getViewAtIndex(2) // Returns second child\n * ```\n */\nexport function createTransactionPlayback(\n rootTransaction: DecoderResult,\n options: TransactionPlaybackOptions = {}\n): TransactionPlaybackState {\n const isBatch = isBatchTransaction(rootTransaction)\n const children = getBatchChildren(rootTransaction)\n const childCount = children.length\n const indexCount = isBatch ? childCount + 1 : 2 // batch: 0 + N, single: 0 and 1\n\n // Calculate available indices\n const availableIndices = isBatch\n ? Array.from({ length: childCount + 1 }, (_, i) => i) // [0, 1, 2, ...]\n : [0, 1] // Single: 0 and 1 both valid\n\n return {\n rootTransaction,\n isBatch,\n children,\n indexCount,\n batchInfo: {\n isBatch,\n childCount,\n availableIndices,\n },\n getViewAtIndex: (index: number) =>\n selectViewAtIndex(rootTransaction, index, options),\n getAllViews: () => {\n const views: PlaybackIndexResult[] = []\n for (let i = 0; i < indexCount; i++) {\n views.push(selectViewAtIndex(rootTransaction, i, options))\n }\n return views\n },\n }\n}\n\n/**\n * Simplified composable that just returns the view at a specific index\n *\n * @example\n * ```typescript\n * // Vue\n * const index = ref(1) // Always show main transaction, skip batch summaries\n * const result = useTransactionPlayback(transaction, index, { framework: 'lit' })\n *\n * // React\n * const [index, setIndex] = useState(1)\n * const result = useTransactionPlayback(transaction, index, { framework: 'lit' })\n * ```\n */\nexport function useTransactionPlayback(\n rootTransaction: DecoderResult,\n index: number,\n options: TransactionPlaybackOptions = {}\n): PlaybackIndexResult {\n return selectViewAtIndex(rootTransaction, index, options)\n}\n\n/**\n * Helper to check if an index is valid for a transaction\n */\nexport function isValidPlaybackIndex(\n transaction: DecoderResult,\n index: number\n): boolean {\n const isBatch = isBatchTransaction(transaction)\n\n if (!isBatch) {\n return index === 0 || index === 1\n }\n\n const childCount = getBatchChildren(transaction).length\n return index >= 0 && index <= childCount\n}\n\n/**\n * Helper to get the range of valid indices for a transaction\n */\nexport function getValidPlaybackIndices(transaction: DecoderResult): number[] {\n const isBatch = isBatchTransaction(transaction)\n\n if (!isBatch) {\n return [0, 1]\n }\n\n const childCount = getBatchChildren(transaction).length\n return Array.from({ length: childCount + 1 }, (_, i) => i)\n}\n","import type {\n AddressIdentityCache,\n DataKey,\n DecoderResult,\n EnhancedInfo,\n} from '@lukso/transaction-decoder'\nimport {\n fetchMultipleAddresses,\n getGraphQLEndpoint,\n} from '@lukso/transaction-decoder'\nimport type { Chain } from 'viem'\nimport { getGlobalLoader, ViewLoadingError } from '../registry/view-loader'\nimport { getGlobalRegistry } from '../registry/view-registry'\nimport type {\n ViewMatch,\n ViewMatchOptions,\n ViewRegistry,\n} from '../types/view-matching'\n\n/**\n * Options for the transaction view composable\n */\nexport interface UseTransactionViewOptions extends Partial<ViewMatchOptions> {\n /** Custom registry to use instead of global */\n registry?: ViewRegistry\n /** Whether to automatically load the best matching component */\n autoLoad?: boolean\n /** Fallback view ID to use if no matches found */\n fallbackViewId?: string\n /** Whether to resolve addresses for this view (uses transaction.addresses array) */\n resolve?: boolean\n /** Chain for address resolution (required if resolve: true) */\n chain?: Chain\n /** Optional cache adapter for address resolution */\n addressCache?: AddressIdentityCache\n}\n\n/**\n * Result from the transaction view composable\n */\nexport interface UseTransactionViewResult {\n /** All matching views sorted by score */\n matches: ViewMatch[]\n /** The best matching view (highest score) */\n bestMatch: ViewMatch | null\n /** The loaded component (if autoLoad is true) */\n component: any\n /** Loading state */\n isLoading: boolean\n /** Error state */\n error: ViewLoadingError | null\n /** Address resolution loading state */\n isResolvingAddresses: boolean\n /** Resolved address data map (if resolve: true) */\n resolvedAddresses: Record<string, EnhancedInfo>\n /** Function to manually load a specific match */\n loadMatch: (match: ViewMatch) => Promise<any>\n /** Function to load the best match */\n loadBestMatch: () => Promise<any>\n /** Function to refresh matches (useful if registry changes) */\n refreshMatches: () => void\n /** Function to manually trigger address resolution */\n resolveAddresses: () => Promise<void>\n}\n\n/**\n * Framework-agnostic composable for finding and loading transaction views\n *\n * This is the main entry point for the view system. It handles:\n * - Finding matching views based on transaction data\n * - Loading components using the appropriate strategy\n * - Providing a consistent API across all frameworks\n *\n * Usage in Vue:\n * ```ts\n * const { bestMatch, component, isLoading, resolvedAddresses } = useTransactionView(transaction, {\n * framework: 'lit',\n * autoLoad: true,\n * resolve: true, // Auto-resolve addresses from transaction.addresses array\n * chain: lukso, // Required for address resolution\n * addressCache: cache // Optional cache adapter\n * })\n * ```\n *\n * Usage in React/React Native:\n * ```ts\n * const { bestMatch, component, loadBestMatch, resolvedAddresses, isResolvingAddresses } = useTransactionView(transaction, {\n * framework: 'react-native',\n * resolve: true,\n * chain: luksoTestnet,\n * addressCache: myCache\n * })\n * useEffect(() => {\n * loadBestMatch()\n * }, [transaction])\n * ```\n */\nexport function useTransactionView(\n transaction: DecoderResult,\n options: UseTransactionViewOptions\n): UseTransactionViewResult {\n const {\n registry = getGlobalRegistry(),\n autoLoad = false,\n fallbackViewId,\n framework = 'lit',\n minScore = 0,\n maxMatches,\n includeFrameworkConfig = true,\n resolve = false,\n chain,\n addressCache,\n } = options\n\n const loader = getGlobalLoader()\n\n // Internal state (framework-specific implementations will handle reactivity)\n let matches: ViewMatch[] = []\n let bestMatch: ViewMatch | null = null\n let component: any = null\n let isLoading = false\n let error: ViewLoadingError | null = null\n let isResolvingAddresses = false\n let resolvedAddresses: Record<string, EnhancedInfo> = {}\n\n // Find matching views\n const refreshMatches = () => {\n const matchOptions: ViewMatchOptions = {\n framework: framework as any,\n minScore,\n maxMatches,\n includeFrameworkConfig,\n }\n\n matches = registry.findMatches(transaction, matchOptions)\n bestMatch = matches[0] || null\n\n // If no matches and we have a fallback, try to get it\n if (!bestMatch && fallbackViewId) {\n const fallbackView = registry.getView(fallbackViewId)\n if (fallbackView?.frameworks[framework]) {\n bestMatch = {\n view: fallbackView,\n score: 0,\n matchedCriteria: [],\n frameworkConfig: includeFrameworkConfig\n ? fallbackView.frameworks[framework]\n : undefined,\n }\n }\n }\n }\n\n // Load a specific match\n const loadMatch = async (match: ViewMatch): Promise<any> => {\n if (!match.frameworkConfig) {\n throw new ViewLoadingError(\n `No framework config for view \"${match.view.id}\" and framework \"${framework}\"`,\n { type: 'dynamic-import', path: '' },\n {} as any\n )\n }\n\n isLoading = true\n error = null\n\n try {\n const loadedComponent = await loader.loadFromMatch(match)\n component = loadedComponent\n return loadedComponent\n } catch (err) {\n error =\n err instanceof ViewLoadingError\n ? err\n : new ViewLoadingError(\n 'Unknown loading error',\n match.frameworkConfig.loader,\n match.frameworkConfig,\n err instanceof Error ? err : new Error(String(err))\n )\n throw error\n } finally {\n isLoading = false\n }\n }\n\n // Load the best match\n const loadBestMatch = async (): Promise<any> => {\n if (!bestMatch) {\n throw new Error('No matching view found for transaction')\n }\n return loadMatch(bestMatch)\n }\n\n // Address resolution function\n const resolveAddressesFunc = async (): Promise<void> => {\n if (\n !resolve ||\n !transaction.addresses ||\n transaction.addresses.length === 0\n ) {\n return\n }\n\n if (!chain) {\n console.warn(\n 'Address resolution requested but no chain provided. Pass chain option to resolve addresses.'\n )\n return\n }\n\n isResolvingAddresses = true\n\n try {\n // Convert addresses to DataKey format\n const dataKeys: DataKey[] = transaction.addresses\n .filter((addr) => addr && typeof addr === 'string')\n .map((addr) => addr.toLowerCase() as DataKey)\n\n if (dataKeys.length === 0) {\n return\n }\n\n // Get GraphQL endpoint based on chain\n const endpoint = getGraphQLEndpoint(chain)\n\n // Use raw fetchMultipleAddresses with optional cache\n const resolvedMap = await fetchMultipleAddresses(\n dataKeys,\n endpoint,\n addressCache\n )\n\n // Convert Map to Record for easier consumption\n const resolved: Record<string, EnhancedInfo> = {}\n resolvedMap.forEach((enhancedInfo, dataKey) => {\n resolved[dataKey] = enhancedInfo\n })\n\n resolvedAddresses = resolved\n } catch (err) {\n console.error('Address resolution failed:', err)\n } finally {\n isResolvingAddresses = false\n }\n }\n\n // Initialize\n refreshMatches()\n\n // Auto-resolve addresses if requested\n if (resolve) {\n resolveAddressesFunc().catch((err) => {\n console.error('Auto address resolution failed:', err)\n })\n }\n\n // Auto-load if requested\n if (autoLoad && bestMatch) {\n loadBestMatch().catch((err) => {\n console.error('Auto-load failed:', err)\n })\n }\n\n return {\n matches,\n bestMatch,\n component,\n isLoading,\n error,\n isResolvingAddresses,\n resolvedAddresses,\n loadMatch,\n loadBestMatch,\n refreshMatches,\n resolveAddresses: resolveAddressesFunc,\n }\n}\n\n/**\n * Simplified version that just returns the best matching view without loading\n */\nexport function findBestTransactionView(\n transaction: DecoderResult,\n framework: 'lit' | 'rn',\n registry?: ViewRegistry\n): ViewMatch | null {\n const reg = registry || getGlobalRegistry()\n const matches = reg.findMatches(transaction, {\n framework,\n includeFrameworkConfig: true,\n })\n return matches.length > 0 ? matches[0] : null\n}\n\n/**\n * Get all matching views without loading\n */\nexport function findAllTransactionViews(\n transaction: DecoderResult,\n framework: 'lit' | 'rn',\n registry?: ViewRegistry\n): ViewMatch[] {\n const reg = registry || getGlobalRegistry()\n return reg.findMatches(transaction, {\n framework,\n includeFrameworkConfig: true,\n })\n}\n","import type {\n FrameworkViewConfig,\n ViewLoader,\n ViewMatch,\n} from '../types/view-matching'\n\n/**\n * Error thrown when view loading fails\n */\nexport class ViewLoadingError extends Error {\n public readonly loader: ViewLoader\n public readonly config: FrameworkViewConfig\n public override readonly cause?: Error\n\n constructor(\n message: string,\n loader: ViewLoader,\n config: FrameworkViewConfig,\n cause?: Error\n ) {\n super(message)\n this.name = 'ViewLoadingError'\n this.loader = loader\n this.config = config\n this.cause = cause\n }\n}\n\n/**\n * Framework-agnostic view loader that handles different loading strategies\n */\nexport class UniversalViewLoader {\n private cache = new Map<string, any>()\n\n /**\n * Load a component based on the framework configuration\n */\n async loadComponent(config: FrameworkViewConfig): Promise<any> {\n const cacheKey = this.getCacheKey(config)\n\n // Return cached component if available\n if (this.cache.has(cacheKey)) {\n return this.cache.get(cacheKey)\n }\n\n try {\n const component = await this.loadByStrategy(config.loader)\n this.cache.set(cacheKey, component)\n return component\n } catch (error) {\n throw new ViewLoadingError(\n `Failed to load component \"${config.component}\"`,\n config.loader,\n config,\n error instanceof Error ? error : new Error(String(error))\n )\n }\n }\n\n /**\n * Load a component from a view match\n */\n async loadFromMatch(match: ViewMatch): Promise<any> {\n if (!match.frameworkConfig) {\n throw new ViewLoadingError(\n `No framework config available for view \"${match.view.id}\"`,\n { type: 'dynamic-import', path: '' },\n {} as FrameworkViewConfig\n )\n }\n\n return this.loadComponent(match.frameworkConfig)\n }\n\n /**\n * Load component using the specific strategy\n */\n private async loadByStrategy(loader: ViewLoader): Promise<any> {\n switch (loader.type) {\n case 'dynamic-import':\n return this.loadDynamicImport(loader.path)\n\n case 'static-import':\n return this.loadStaticImport(loader.path)\n\n case 'custom-element':\n return this.loadCustomElement(loader.tagName)\n\n case 'registry-lookup':\n return this.loadFromRegistry(loader.registryKey)\n\n case 'custom':\n return loader.loader({} as FrameworkViewConfig) // Will be passed proper config in real usage\n\n default:\n throw new Error(`Unknown loader type: ${(loader as any).type}`)\n }\n }\n\n /**\n * Dynamic import strategy (most common)\n * Supports both static strings and lazy-loaded callbacks\n */\n private async loadDynamicImport(\n path: string | (() => Promise<any>)\n ): Promise<any> {\n // Handle callback-based lazy loading\n if (typeof path === 'function') {\n const module = await path()\n\n // Handle different export patterns\n if (module.default) {\n return module.default\n }\n\n return module\n }\n\n // Handle string-based path (static)\n const module = await import(/* @vite-ignore */ path)\n\n // Handle different export patterns\n if (module.default) {\n return module.default\n }\n\n // If no default export, return the entire module\n return module\n }\n\n /**\n * Static import strategy (requires bundler support)\n * Supports both static strings and lazy-loaded callbacks\n */\n private async loadStaticImport(\n path: string | (() => Promise<any>)\n ): Promise<any> {\n // Handle callback-based lazy loading\n if (typeof path === 'function') {\n const module = await path()\n\n if (module.default) {\n return module.default\n }\n\n return module\n }\n\n // This would typically be handled by bundler transformation\n // For now, fall back to dynamic import\n console.warn(\n 'Static import not implemented, falling back to dynamic import'\n )\n return this.loadDynamicImport(path)\n }\n\n /**\n * Custom element strategy (for Lit components)\n */\n private async loadCustomElement(tagName: string): Promise<any> {\n // Wait for custom element to be defined\n if (typeof window !== 'undefined' && window.customElements) {\n await window.customElements.whenDefined(tagName)\n return { tagName, type: 'custom-element' }\n }\n\n throw new Error('Custom elements not available in this environment')\n }\n\n /**\n * Registry lookup strategy (for pre-registered components)\n */\n private async loadFromRegistry(registryKey: string): Promise<any> {\n // This would look up in a component registry\n // Implementation depends on framework\n throw new Error(`Registry lookup not implemented for key: ${registryKey}`)\n }\n\n /**\n * Generate cache key for component config\n */\n private getCacheKey(config: FrameworkViewConfig): string {\n const { loader, component, package: pkg } = config\n return JSON.stringify({ loader, component, package: pkg })\n }\n\n /**\n * Clear the component cache\n */\n clearCache(): void {\n this.cache.clear()\n }\n\n /**\n * Get cache statistics\n */\n getCacheStats(): { size: number; keys: string[] } {\n return {\n size: this.cache.size,\n keys: Array.from(this.cache.keys()),\n }\n }\n}\n\n/**\n * Singleton loader instance\n */\nlet globalLoader: UniversalViewLoader | null = null\n\n/**\n * Get the global view loader\n */\nexport function getGlobalLoader(): UniversalViewLoader {\n if (!globalLoader) {\n globalLoader = new UniversalViewLoader()\n }\n return globalLoader\n}\n\n/**\n * Set a custom global loader (useful for testing)\n */\nexport function setGlobalLoader(loader: UniversalViewLoader): void {\n globalLoader = loader\n}\n\n/**\n * Framework-specific helpers for strategically optimized loading patterns\n *\n * Following our Suffering Economics optimization, we support:\n * - Lit Web Components (universal web compatibility) - REQUIRED\n * - Vue (native Vue optimization) - OPTIONAL\n * - React Native (mobile-native optimization) - OPTIONAL (WebView fallback available)\n *\n * All loaders support lazy loading via callbacks:\n * ```typescript\n * // Static (bundled)\n * vueComponent('./Component.vue')\n *\n * // Lazy (loaded on demand)\n * vueComponent(() => import('./Component.vue'))\n * ```\n */\nexport const LoaderHelpers = {\n /**\n * Create a Lit custom element loader (universal web compatibility)\n */\n litComponent(tagName: string): ViewLoader {\n return { type: 'custom-element', tagName }\n },\n\n /**\n * Create a Vue component loader (native Vue, optional)\n * Supports both static paths and lazy-loaded callbacks\n */\n vueComponent(path: string | (() => Promise<any>)): ViewLoader {\n return { type: 'dynamic-import', path }\n },\n\n /**\n * Create a React Native JSX dynamic import loader (mobile-native, optional)\n * Supports both static paths and lazy-loaded callbacks\n */\n rnComponent(path: string | (() => Promise<any>)): ViewLoader {\n return { type: 'dynamic-import', path }\n },\n\n /**\n * Create a custom loader function for advanced use cases\n */\n custom(loader: (config: FrameworkViewConfig) => Promise<any>): ViewLoader {\n return { type: 'custom', loader }\n },\n\n // Legacy helpers for compilation pipelines (Vue/React → Lit)\n /**\n * @deprecated Use litComponent() instead. This exists for compilation pipeline compatibility.\n */\n vueToLitCompiled(tagName: string): ViewLoader {\n console.warn(\n 'vueToLitCompiled is deprecated. Use litComponent() - the output is the same.'\n )\n return { type: 'custom-element', tagName }\n },\n\n /**\n * @deprecated Use litComponent() instead. This exists for compilation pipeline compatibility.\n */\n reactToLitCompiled(tagName: string): ViewLoader {\n console.warn(\n 'reactToLitCompiled is deprecated. Use litComponent() - the output is the same.'\n )\n return { type: 'custom-element', tagName }\n },\n\n /**\n * @deprecated Use rnComponent() instead. Updated for better TypeScript support.\n */\n reactNativeComponent(path: string): ViewLoader {\n console.warn(\n 'reactNativeComponent is deprecated. Use rnComponent() instead.'\n )\n return { type: 'dynamic-import', path }\n },\n}\n","/**\n * TanStack Query integration for address resolution\n * Provides proper cache keys and query functions\n */\n\nimport type { ResolvedAddress } from './useAddressResolution'\nimport { resolveAddress, resolveAddresses } from './useAddressResolution'\n\n/**\n * Create TanStack Query key for address resolution\n */\nexport function getAddressQueryKey(\n address: string,\n chainId?: number\n): (string | number)[] {\n // Include chainId to ensure cache isolation per chain\n return ['address', address.toLowerCase(), chainId || 'current']\n}\n\n/**\n * Create TanStack Query key for batch address resolution\n */\nexport function getAddressesQueryKey(\n addresses: string[],\n chainId?: number\n): (string | number)[] {\n // Sort addresses for consistent cache keys\n const sortedAddresses = [...addresses]\n .map((addr) => addr.toLowerCase())\n .sort()\n return ['addresses', sortedAddresses.join(','), chainId || 'current']\n}\n\n/**\n * Query function for single address resolution\n */\nexport async function queryAddress({\n queryKey,\n}: {\n queryKey: (string | number)[]\n}): Promise<ResolvedAddress> {\n const [, address, chainIdOrCurrent] = queryKey\n const chainId =\n chainIdOrCurrent === 'current' ? undefined : (chainIdOrCurrent as number)\n\n return resolveAddress(address as string, chainId)\n}\n\n/**\n * Query function for batch address resolution\n */\nexport async function queryAddresses({\n queryKey,\n}: {\n queryKey: (string | number)[]\n}): Promise<Map<string, ResolvedAddress>> {\n const [, addressesStr, chainIdOrCurrent] = queryKey\n const chainId =\n chainIdOrCurrent === 'current' ? undefined : (chainIdOrCurrent as number)\n const addresses = (addressesStr as string).split(',')\n\n return resolveAddresses(addresses, chainId)\n}\n\n/**\n * Helper for React TanStack Query usage\n */\nexport const addressQueryOptions = {\n /**\n * Single address query options\n */\n single: (address: string, chainId?: number) => ({\n queryKey: getAddressQueryKey(address, chainId),\n queryFn: queryAddress,\n staleTime: 5 * 60 * 1000, // 5 minutes\n gcTime: 10 * 60 * 1000, // 10 minutes (formerly cacheTime)\n }),\n\n /**\n * Batch addresses query options\n */\n batch: (addresses: string[], chainId?: number) => ({\n queryKey: getAddressesQueryKey(addresses, chainId),\n queryFn: queryAddresses,\n staleTime: 5 * 60 * 1000, // 5 minutes\n gcTime: 10 * 60 * 1000, // 10 minutes\n }),\n}\n\n/**\n * Helper for Vue TanStack Query usage\n */\nexport const addressQueryOptionsVue = {\n /**\n * Single address query options for Vue Query\n */\n single: (address: string, chainId?: number) => ({\n queryKey: getAddressQueryKey(address, chainId),\n queryFn: queryAddress,\n staleTime: 5 * 60 * 1000,\n cacheTime: 10 * 60 * 1000, // Vue Query still uses cacheTime\n }),\n\n /**\n * Batch addresses query options for Vue Query\n */\n batch: (addresses: string[], chainId?: number) => ({\n queryKey: getAddressesQueryKey(addresses, chainId),\n queryFn: queryAddresses,\n staleTime: 5 * 60 * 1000,\n cacheTime: 10 * 60 * 1000,\n }),\n}\n\n/**\n * Invalidate address cache for a specific chain\n * Useful when switching chains\n */\nexport function getInvalidateAddressesPattern(\n chainId?: number\n): (string | number)[] {\n return ['address', chainId || 'current']\n}\n\n/**\n * Get all possible query keys for an address across all chains\n * Useful for invalidating cache when address profile changes\n */\nexport function getAllAddressQueryKeys(address: string): (string | number)[][] {\n return [\n ['address', address.toLowerCase(), 'current'],\n ['address', address.toLowerCase(), 42], // mainnet\n ['address', address.toLowerCase(), 4201], // testnet\n ]\n}\n","/**\n * View Events and Header Information Types\n *\n * Defines the event system for transaction views to communicate\n * with their parent containers about header display and other UI concerns.\n */\n\n/**\n * Header information that a view can provide to its parent container\n *\n * Views can emit this information to override the default header\n * that would be derived from the transaction's top-level from/to addresses.\n *\n * @example\n * ```typescript\n * // Inside a transfer view component\n * this.dispatchEvent(new CustomEvent('header-info', {\n * bubbles: true,\n * composed: true,\n * detail: {\n * from: transferFromAddress,\n * to: transferToAddress,\n * title: 'LSP7 Token Transfer'\n * }\n * }))\n * ```\n */\nexport interface TransactionHeaderInfo {\n /**\n * The \"from\" address to display in the header\n * Overrides the transaction's top-level from address\n */\n from?: string\n\n /**\n * The \"to\" address to display in the header\n * Overrides the transaction's top-level to address\n */\n to?: string\n\n /**\n * Optional title for the transaction\n * @example \"LSP7 Token Transfer\", \"Set Data\", \"Execute\"\n */\n title?: string\n\n /**\n * Optional subtitle or description\n * @example \"Send 100 tokens\", \"Update profile data\"\n */\n subtitle?: string\n\n /**\n * Optional icon identifier\n * @example \"transfer\", \"setdata\", \"execute\"\n */\n icon?: string\n\n /**\n * Optional additional metadata\n * Can be used for custom header rendering\n */\n metadata?: Record<string, any>\n}\n\n/**\n * Type-safe custom event for header information\n */\nexport interface HeaderInfoEvent extends CustomEvent {\n detail: TransactionHeaderInfo\n}\n\n/**\n * Transaction modification information\n *\n * Views emit this to modify their transaction's data (e.g., changing a parameter).\n * The view encodes its LOCAL transaction data, and the parent handles re-wrapping\n * if the transaction is inside Execute or ExecuteBatch wrappers.\n *\n * @example\n * ```typescript\n * // In a transfer view, user clicks \"Force Transfer\" checkbox\n * const newData = encodeFunctionData({\n * abi: LSP7_ABI,\n * functionName: 'transfer',\n * args: [from, to, amount, true, data] // force = true\n * })\n *\n * dispatchTransactionModification(this, {\n * data: newData,\n * transactionIndex: this.index,\n * reason: 'User enabled force transfer to EOA',\n * userInitiated: true\n * })\n * ```\n */\nexport interface TransactionModification {\n /**\n * The modified data for THIS transaction level (not wrapped)\n *\n * This is the encoded function call for the current transaction only,\n * not wrapped in Execute or Batch calls. The parent container handles re-wrapping.\n */\n data: `0x${string}`\n\n /**\n * The playback index this modification applies to\n *\n * - 0 = batch summary (modifies batch itself)\n * - 1 = first transaction (or single tx)\n * - 2 = second child transaction\n * - etc.\n *\n * This must match the `index` prop of <transaction-playback>\n */\n transactionIndex: number\n\n /**\n * Human-readable explanation of why this modification occurred\n *\n * @example \"User enabled force transfer to EOA\"\n * @example \"Slippage tolerance increased to 2%\"\n * @example \"Gas limit adjusted for complex operation\"\n */\n reason: string\n\n /**\n * Whether this modification was triggered by user interaction\n *\n * - true: User clicked checkbox, changed input, adjusted slider, etc.\n * - false: Automatic adjustment by view logic\n */\n userInitiated: boolean\n\n /**\n * Optional structured summary for quick display/logging\n */\n summary?: {\n /** Name of the field that changed */\n field: string\n\n /** Human-readable old value */\n oldValue: string\n\n /** Human-readable new value */\n newValue: string\n }\n\n /**\n * Optional validation information\n */\n validation?: {\n /** Whether the modification is valid */\n isValid: boolean\n\n /** Error message if invalid */\n error?: string\n\n /** Warning messages (modification is valid but user should be aware) */\n warnings?: string[]\n }\n}\n\n/**\n * Extended modification info added by transaction-playback\n *\n * This is what the top-level container receives after transaction-playback\n * adds context about where in the transaction tree this modification applies.\n */\nexport interface TransactionModificationWithContext\n extends TransactionModification {\n /**\n * Path from root transaction to this transaction\n *\n * @example [1] - Simple transaction at index 1\n * @example [0, 2] - Batch at index 0, child at index 2\n * @example [0, 1, 0] - Nested batch: batch[0].children[1].children[0]\n */\n transactionPath: number[]\n\n /**\n * The full local transaction object with modified data\n * (Before re-wrapping)\n */\n localTransaction: any // DecoderResult, but avoiding circular dep\n\n /**\n * Re-decoded result for verification\n * Parent should verify this decodes successfully before applying\n */\n decodedResult: any // DecoderResult\n}\n\n/**\n * Type-safe custom event for transaction modifications\n */\nexport interface TransactionModificationEvent extends CustomEvent {\n detail: TransactionModification\n}\n\n/**\n * Event type names for transaction views\n */\nexport const TransactionViewEvents = {\n /**\n * Emitted when a view wants to provide custom header information\n * Parent containers should listen for this event and update their header accordingly\n */\n HEADER_INFO: 'header-info',\n\n /**\n * Emitted when a view modifies its transaction data\n * Parent containers should listen, re-wrap if needed, and update the transaction\n */\n TRANSACTION_MODIFICATION: 'transaction-modification',\n\n /**\n * Emitted when a view's state changes (future use)\n * @example Loading state, error state, interactive state changes\n */\n STATE_CHANGE: 'view-state-change',\n\n /**\n * Emitted when a view has an action for the user (future use)\n * @example \"Approve\", \"Reject\", \"Sign\"\n */\n ACTION: 'view-action',\n} as const\n\n/**\n * Helper function to dispatch header info event\n * Use this in view components to emit header information\n *\n * @example\n * ```typescript\n * import { dispatchHeaderInfo } from '@lukso/transaction-view-headless'\n *\n * class MyTransferView extends LitElement {\n * connectedCallback() {\n * super.connectedCallback()\n * dispatchHeaderInfo(this, {\n * from: this.transferFrom,\n * to: this.transferTo,\n * title: 'Token Transfer'\n * })\n * }\n * }\n * ```\n */\nexport function dispatchHeaderInfo(\n element: HTMLElement,\n headerInfo: TransactionHeaderInfo\n): void {\n element.dispatchEvent(\n new CustomEvent(TransactionViewEvents.HEADER_INFO, {\n bubbles: true,\n composed: true, // Allows event to cross shadow DOM boundaries\n detail: headerInfo,\n })\n )\n}\n\n/**\n * Type guard to check if an event is a HeaderInfoEvent\n */\nexport function isHeaderInfoEvent(event: Event): event is HeaderInfoEvent {\n return (\n event instanceof CustomEvent &&\n event.type === TransactionViewEvents.HEADER_INFO\n )\n}\n\n/**\n * Helper function to dispatch transaction modification event\n * Use this in view components to emit transaction modifications\n *\n * @example\n * ```typescript\n * import { dispatchTransactionModification } from '@lukso/transaction-view-headless'\n *\n * class MyTransferView extends LitElement {\n * private handleForceCheckbox(checked: boolean) {\n * const newData = encodeFunctionData({\n * abi: LSP7_ABI,\n * functionName: 'transfer',\n * args: [...args, checked]\n * })\n *\n * dispatchTransactionModification(this, {\n * data: newData,\n * transactionIndex: this.index,\n * reason: 'User enabled force transfer',\n * userInitiated: true\n * })\n * }\n * }\n * ```\n */\nexport function dispatchTransactionModification(\n element: HTMLElement,\n modification: TransactionModification\n): void {\n element.dispatchEvent(\n new CustomEvent(TransactionViewEvents.TRANSACTION_MODIFICATION, {\n bubbles: true,\n composed: true,\n detail: modification,\n })\n )\n}\n\n/**\n * Type guard to check if an event is a TransactionModificationEvent\n */\nexport function isTransactionModificationEvent(\n event: Event\n): event is TransactionModificationEvent {\n return (\n event instanceof CustomEvent &&\n event.type === TransactionViewEvents.TRANSACTION_MODIFICATION\n )\n}\n"],"mappings":"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","names":["fetchMultipleAddresses","getGraphQLEndpoint","resolveAddress","module","addressCache"]}
package/dist/index.js CHANGED
@@ -1048,7 +1048,10 @@ var UniversalViewLoader = class {
1048
1048
  }
1049
1049
  return module2;
1050
1050
  }
1051
- const module = await import(path);
1051
+ const module = await import(
1052
+ /* @vite-ignore */
1053
+ path
1054
+ );
1052
1055
  if (module.default) {
1053
1056
  return module.default;
1054
1057
  }