@lukso/transaction-decoder 1.3.0-dev.c21633f → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/dist/browser.cjs +73 -41
  2. package/dist/browser.cjs.map +1 -1
  3. package/dist/browser.d.cts +1 -1
  4. package/dist/browser.d.ts +1 -1
  5. package/dist/browser.js +4 -4
  6. package/dist/cdn/transaction-decoder.global.js +13 -13
  7. package/dist/cdn/transaction-decoder.global.js.map +1 -1
  8. package/dist/{chunk-2ZO6MJJX.js → chunk-G7JZHSYX.js} +12 -11
  9. package/dist/chunk-G7JZHSYX.js.map +1 -0
  10. package/dist/{chunk-FKBKAWB3.js → chunk-GGBHTWJL.js} +5 -5
  11. package/dist/chunk-GGBHTWJL.js.map +1 -0
  12. package/dist/{chunk-NDBDNXBI.js → chunk-GXZOF3QY.js} +27 -3
  13. package/dist/chunk-GXZOF3QY.js.map +1 -0
  14. package/dist/{chunk-T4H2HHIB.js → chunk-XVHJWV5U.js} +32 -25
  15. package/dist/chunk-XVHJWV5U.js.map +1 -0
  16. package/dist/data.cjs +62 -31
  17. package/dist/data.cjs.map +1 -1
  18. package/dist/data.d.cts +2 -2
  19. package/dist/data.d.ts +2 -2
  20. package/dist/data.js +2 -2
  21. package/dist/index.cjs +73 -41
  22. package/dist/index.cjs.map +1 -1
  23. package/dist/index.d.cts +2 -2
  24. package/dist/index.d.ts +2 -2
  25. package/dist/index.js +4 -4
  26. package/dist/server.cjs +43 -31
  27. package/dist/server.cjs.map +1 -1
  28. package/dist/server.d.cts +2 -1
  29. package/dist/server.d.ts +2 -1
  30. package/dist/server.js +12 -7
  31. package/dist/server.js.map +1 -1
  32. package/dist/{utils-BEpSreRR.d.cts → utils-CBAkjQh3.d.cts} +1 -1
  33. package/dist/{utils-De_c6fUK.d.ts → utils-xT9-km0r.d.ts} +1 -1
  34. package/package.json +3 -3
  35. package/src/core/dataModel.ts +31 -1
  36. package/src/core/integrateDecoder.ts +2 -1
  37. package/src/decoder/browserCache.ts +6 -1
  38. package/src/decoder/errors.ts +2 -2
  39. package/src/decoder/events.ts +3 -3
  40. package/src/decoder/functionSignature.ts +9 -9
  41. package/src/decoder/getDataFromExternalSources.ts +2 -2
  42. package/src/decoder/interfaces.ts +1 -1
  43. package/src/decoder/kvCache.ts +6 -1
  44. package/src/decoder/lruCache.ts +6 -1
  45. package/src/decoder/lsp7TransferBatch.test.ts +3 -0
  46. package/src/decoder/plugins/enhanceBurntPix.ts +2 -1
  47. package/src/decoder/plugins/enhanceGraffiti.ts +17 -3
  48. package/src/decoder/plugins/enhanceLSP26FollowerSystem.ts +8 -4
  49. package/src/decoder/plugins/enhanceLSP6KeyManager.ts +1 -0
  50. package/src/decoder/plugins/enhanceLSP7DigitalAsset.ts +7 -5
  51. package/src/decoder/plugins/enhanceLSP9Vault.ts +8 -7
  52. package/src/decoder/plugins/enhanceRetrieveAbi.ts +6 -5
  53. package/src/decoder/plugins/index.ts +1 -3
  54. package/src/decoder/plugins/schemaDefault.ts +4 -3
  55. package/src/decoder/plugins/standardPlugin.ts +1 -1
  56. package/src/decoder/singleGQL.ts +2 -2
  57. package/src/decoder/transaction.ts +2 -1
  58. package/src/decoder/utils.ts +2 -2
  59. package/src/example/usage.ts +4 -3
  60. package/src/server/addressResolver.ts +1 -1
  61. package/src/server/decodeTransactionSync.ts +1 -0
  62. package/src/server/decodeTransactionsBatch.ts +1 -1
  63. package/src/server/finishDecoding.ts +8 -4
  64. package/src/server/lsp23Resolver.ts +3 -2
  65. package/src/server/types.ts +1 -1
  66. package/src/shared/addressResolver.ts +4 -4
  67. package/src/utils/json-bigint.ts +4 -4
  68. package/dist/chunk-2ZO6MJJX.js.map +0 -1
  69. package/dist/chunk-FKBKAWB3.js.map +0 -1
  70. package/dist/chunk-NDBDNXBI.js.map +0 -1
  71. package/dist/chunk-T4H2HHIB.js.map +0 -1
@@ -1,16 +1,16 @@
1
1
  import {
2
2
  consumerModel,
3
3
  decodeTransaction
4
- } from "./chunk-NDBDNXBI.js";
4
+ } from "./chunk-GXZOF3QY.js";
5
5
  import {
6
6
  fetchMultipleAddresses
7
- } from "./chunk-FKBKAWB3.js";
7
+ } from "./chunk-GGBHTWJL.js";
8
8
  import {
9
9
  __name,
10
10
  collectDataKeys,
11
11
  defaultPlugins,
12
12
  defaultSchemaPlugins
13
- } from "./chunk-T4H2HHIB.js";
13
+ } from "./chunk-XVHJWV5U.js";
14
14
 
15
15
  // src/shared/cache.ts
16
16
  function isPromise(value) {
@@ -328,7 +328,7 @@ var DecoderIntegration = class {
328
328
  */
329
329
  async addAndDecodeTransactions(transactions) {
330
330
  const signals = this.dataModel.addTransactions(transactions);
331
- const decodingPromises = transactions.map(async (tx, _index) => {
331
+ const decodingPromises = transactions.map(async (tx, index) => {
332
332
  const transactionOptions = {
333
333
  ...this.decoderOptions,
334
334
  wrappers: []
@@ -567,7 +567,8 @@ function buildLSP23DeploymentQuery(config) {
567
567
  controllerAddresses,
568
568
  profileAddresses,
569
569
  fromBlock = 0,
570
- toBlock
570
+ toBlock,
571
+ chainId
571
572
  } = config;
572
573
  if (profileAddresses && profileAddresses.length > 0) {
573
574
  return {
@@ -650,7 +651,7 @@ function parseLSP23DeploymentsFromHypersync(response, chainId, controllerAddress
650
651
  }
651
652
  }
652
653
  const controllerSet = controllerAddresses ? new Set(controllerAddresses.map((addr) => addr.toLowerCase())) : null;
653
- for (const [txHash, _profileAddress] of create2Traces) {
654
+ for (const [txHash, profileAddress] of create2Traces) {
654
655
  const tx = txMap.get(txHash);
655
656
  if (!tx) continue;
656
657
  if (controllerSet && !controllerSet.has(tx.from.toLowerCase())) {
@@ -688,12 +689,12 @@ var JSONbigString = {
688
689
  /**
689
690
  * Stringify an object, converting BigInt values to strings with 'n' suffix
690
691
  */
691
- stringify: /* @__PURE__ */ __name((obj, _replacer, space) => {
692
+ stringify: /* @__PURE__ */ __name((obj, replacer, space) => {
692
693
  return JSON.stringify(
693
694
  obj,
694
- (_key, value) => {
695
+ (key, value) => {
695
696
  if (typeof value === "bigint") {
696
- return `${value.toString()}n`;
697
+ return value.toString() + "n";
697
698
  }
698
699
  return value;
699
700
  },
@@ -704,7 +705,7 @@ var JSONbigString = {
704
705
  * Parse a JSON string, converting strings ending with 'n' back to BigInt
705
706
  */
706
707
  parse: /* @__PURE__ */ __name((text) => {
707
- return JSON.parse(text, (_key, value) => {
708
+ return JSON.parse(text, (key, value) => {
708
709
  if (typeof value === "string" && /^\d+n$/.test(value)) {
709
710
  return BigInt(value.slice(0, -1));
710
711
  }
@@ -772,4 +773,4 @@ export {
772
773
  getAllData,
773
774
  getAllTransactions
774
775
  };
775
- //# sourceMappingURL=chunk-2ZO6MJJX.js.map
776
+ //# sourceMappingURL=chunk-G7JZHSYX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/shared/cache.ts","../src/client/resolveAddresses.ts","../src/core/addressResolver.ts","../src/core/integrateDecoder.ts","../src/server/lsp23Resolver.ts","../src/utils/json-bigint.ts","../src/index.ts"],"sourcesContent":["import type { DataKey, EnhancedInfo } from '../types'\n\n/**\n * Address identity cache interface\n * Can be implemented with different backends (LRU, Redis, etc.)\n */\nexport interface AddressIdentityCache {\n /**\n * Get cached address data\n */\n get(\n key: DataKey\n ): EnhancedInfo | undefined | Promise<EnhancedInfo | undefined>\n\n /**\n * Set address data in cache\n */\n set(key: DataKey, value: EnhancedInfo): void | Promise<void>\n\n /**\n * Check if address is in cache\n */\n has(key: DataKey): boolean | Promise<boolean>\n\n /**\n * Get multiple addresses at once\n */\n getMany?(\n keys: readonly DataKey[]\n ): Map<DataKey, EnhancedInfo> | Promise<Map<DataKey, EnhancedInfo>>\n\n /**\n * Set multiple addresses at once\n */\n setMany?(entries: Array<[DataKey, EnhancedInfo]>): void | Promise<void>\n\n /**\n * Clear all cached data\n */\n clear?(): void | Promise<void>\n}\n\n/**\n * Type guard to check if value is a promise\n */\nfunction isPromise<T>(value: T | Promise<T>): value is Promise<T> {\n return value instanceof Promise\n}\n\n/**\n * Helper to convert DataKey to cache key string\n */\nexport function getDataKeyCacheKey(key: DataKey): string {\n return key.toLowerCase()\n}\n\n/**\n * Convert a DataKey to the standardized string format\n * @param dataKey - A hex string (address or address:tokenId)\n * @returns The same string\n */\nexport function dataKeyToString(dataKey: DataKey): string {\n return dataKey\n}\n\n/**\n * Parse a string to a DataKey\n * @param str - String in format \"address\" or \"address:tokenId\"\n * @returns DataKey as a hex string\n */\nexport function parseDataKey(str: string): DataKey {\n // Just return the string as-is since DataKey is now always a string\n return str as DataKey\n}\n\n/**\n * Create a simple in-memory address cache\n */\nexport function createMemoryAddressIdentityCache(\n ttlMs: number = 1000 * 60 * 5 // 5 minutes default\n): AddressIdentityCache {\n const cache = new Map<string, { data: EnhancedInfo; expires: number }>()\n\n return {\n get(key: DataKey): EnhancedInfo | undefined {\n const cacheKey = getDataKeyCacheKey(key)\n const entry = cache.get(cacheKey)\n\n if (!entry) return undefined\n\n if (Date.now() > entry.expires) {\n cache.delete(cacheKey)\n return undefined\n }\n\n return entry.data\n },\n\n set(key: DataKey, value: EnhancedInfo): void {\n const cacheKey = getDataKeyCacheKey(key)\n cache.set(cacheKey, {\n data: value,\n expires: Date.now() + ttlMs,\n })\n },\n\n has(key: DataKey): boolean {\n const cacheKey = getDataKeyCacheKey(key)\n const entry = cache.get(cacheKey)\n\n if (!entry) return false\n\n if (Date.now() > entry.expires) {\n cache.delete(cacheKey)\n return false\n }\n\n return true\n },\n\n getMany(keys: DataKey[]): Map<DataKey, EnhancedInfo> {\n const results = new Map<DataKey, EnhancedInfo>()\n\n for (const key of keys) {\n const data = this.get(key)\n if (data && !isPromise(data)) {\n results.set(key, data)\n }\n }\n\n return results\n },\n\n setMany(entries: Array<[DataKey, EnhancedInfo]>): void {\n for (const [key, value] of entries) {\n this.set(key, value)\n }\n },\n\n clear(): void {\n cache.clear()\n },\n }\n}\n","import type { Chain } from 'viem'\nimport type { AddressIdentityCache } from '../shared/cache'\nimport { getDataKeyCacheKey } from '../shared/cache'\nimport type { DataKey, EnhancedInfo } from '../types'\n\nexport interface ResolveAddressesOptions {\n /**\n * API endpoint URL (defaults to '/api/resolveAddresses')\n */\n endpoint?: string\n\n /**\n * Optional cache to check before making API call\n */\n cache?: AddressIdentityCache\n\n /**\n * Maximum number of addresses per batch (defaults to 100)\n */\n batchSize?: number\n\n /**\n * Request timeout in milliseconds (defaults to 10000)\n */\n timeout?: number\n}\n\nexport interface ResolveAddressesResponse {\n success: boolean\n addresses?: Record<string, EnhancedInfo>\n cached?: number\n fetched?: number\n total?: number\n error?: string\n}\n\n/**\n * Resolve addresses using the API endpoint\n * This allows clients to populate the server cache and get resolved addresses\n */\nexport async function resolveAddresses(\n addresses: DataKey[],\n chain: Chain,\n options: ResolveAddressesOptions = {}\n): Promise<Map<DataKey, EnhancedInfo>> {\n const {\n endpoint = '/api/resolveAddresses',\n cache,\n batchSize = 100,\n timeout = 10000,\n } = options\n\n const results = new Map<DataKey, EnhancedInfo>()\n\n if (addresses.length === 0) {\n return results\n }\n\n // Check cache first if provided\n const uncachedAddresses: DataKey[] = []\n\n if (cache) {\n for (const addr of addresses) {\n const cached = await cache.get(addr)\n if (cached) {\n results.set(addr, cached)\n } else {\n uncachedAddresses.push(addr)\n }\n }\n\n if (uncachedAddresses.length === 0) {\n return results\n }\n } else {\n uncachedAddresses.push(...addresses)\n }\n\n // Process in batches\n const batches: DataKey[][] = []\n for (let i = 0; i < uncachedAddresses.length; i += batchSize) {\n batches.push(uncachedAddresses.slice(i, i + batchSize))\n }\n\n // Fetch all batches in parallel\n const batchPromises = batches.map(async (batch) => {\n try {\n // DataKey is now just Hex string, use batch directly\n const apiAddresses = batch\n\n // Make API request with timeout\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), timeout)\n\n const response = await fetch(endpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n chainId: chain.id,\n addresses: apiAddresses,\n }),\n signal: controller.signal,\n })\n\n clearTimeout(timeoutId)\n\n if (!response.ok) {\n console.error(\n `Address resolution failed: ${response.status} ${response.statusText}`\n )\n return\n }\n\n const data: ResolveAddressesResponse = await response.json()\n\n if (data.success && data.addresses) {\n // Convert response back to DataKey -> EnhancedInfo map\n for (const [cacheKey, enhancedInfo] of Object.entries(data.addresses)) {\n // Find the original DataKey that matches this cache key\n const matchingKey = batch.find(\n (key) => getDataKeyCacheKey(key) === cacheKey\n )\n\n if (matchingKey) {\n results.set(matchingKey, enhancedInfo)\n\n // Update cache if provided\n if (cache) {\n await cache.set(matchingKey, enhancedInfo)\n }\n }\n }\n }\n } catch (error) {\n console.error('Failed to resolve addresses batch:', error)\n }\n })\n\n await Promise.all(batchPromises)\n\n return results\n}\n\n/**\n * Create a cache-through address resolver that uses the API\n * This can be used as a drop-in replacement for fetchMultipleAddresses\n */\nexport function createApiAddressResolver(\n chain: Chain,\n options: ResolveAddressesOptions = {}\n) {\n return async (addresses: DataKey[]): Promise<Map<DataKey, EnhancedInfo>> => {\n return resolveAddresses(addresses, chain, options)\n }\n}\n","import type { Chain } from 'viem'\nimport { fetchMultipleAddresses } from '../shared/addressResolver'\nimport type { AddressIdentityCache } from '../shared/cache'\nimport type { DataKey, EnhancedInfo, IDataModel } from '../types'\n\n/**\n * Configuration for address resolver\n */\nexport interface AddressResolverConfig {\n dataModel: IDataModel\n graphqlEndpoint: string\n chain: Chain\n batchSize?: number\n batchDelay?: number\n cache?: AddressIdentityCache\n}\n\n/**\n * Resolve addresses using GraphQL\n * Replaces the old patchValue mechanism\n */\nexport class AddressResolver {\n private dataModel: IDataModel\n private graphqlEndpoint: string\n private batchSize: number\n private batchDelay: number\n private pendingAddresses = new Set<string>()\n private batchTimer?: NodeJS.Timeout\n private cache?: AddressIdentityCache\n\n constructor(config: AddressResolverConfig) {\n this.dataModel = config.dataModel\n this.graphqlEndpoint = config.graphqlEndpoint\n this.batchSize = config.batchSize || 50\n this.batchDelay = config.batchDelay || 100\n this.cache = config.cache\n }\n\n /**\n * Start watching for missing addresses\n */\n startWatching() {\n // Check for missing addresses periodically\n setInterval(() => {\n const missing = this.dataModel.getMissingKeys()\n if (missing.length > 0) {\n this.queueAddresses(missing)\n }\n }, 1000)\n }\n\n /**\n * Queue addresses for batch resolution\n */\n queueAddresses(addresses: DataKey[]) {\n // Add to pending set\n for (const addr of addresses) {\n this.pendingAddresses.add(addr)\n }\n\n // Clear existing timer\n if (this.batchTimer) {\n clearTimeout(this.batchTimer)\n }\n\n // Set new timer\n this.batchTimer = setTimeout(() => {\n this.processBatch()\n }, this.batchDelay)\n\n // Process immediately if batch is full\n if (this.pendingAddresses.size >= this.batchSize) {\n clearTimeout(this.batchTimer)\n this.processBatch()\n }\n }\n\n /**\n * Process a batch of addresses\n */\n private async processBatch() {\n const batch = Array.from(this.pendingAddresses).slice(0, this.batchSize)\n if (batch.length === 0) return\n\n // Remove from pending\n for (const key of batch) {\n this.pendingAddresses.delete(key)\n }\n\n // Convert batch keys back to DataKey format\n const dataKeys: DataKey[] = batch.map((key) => {\n return key as DataKey\n })\n\n try {\n // Fetch data using shared implementation with cache\n const results = await fetchMultipleAddresses(\n dataKeys,\n this.graphqlEndpoint,\n this.cache\n )\n\n // Convert to array for injection\n const enhancedData: EnhancedInfo[] = Array.from(results.values())\n\n // Inject data into model\n if (enhancedData.length > 0) {\n this.dataModel.injectData(enhancedData)\n }\n } catch (error) {\n console.error('Failed to resolve addresses:', error)\n\n // Mark addresses as having errors\n for (const key of dataKeys) {\n this.dataModel.setError(key, 'Failed to fetch address data')\n }\n }\n\n // Continue processing if more pending\n if (this.pendingAddresses.size > 0) {\n this.batchTimer = setTimeout(() => {\n this.processBatch()\n }, this.batchDelay)\n }\n }\n\n /**\n * Stop watching for addresses\n */\n stopWatching() {\n if (this.batchTimer) {\n clearTimeout(this.batchTimer)\n }\n }\n}\n","import { effect } from '@preact/signals-core'\nimport type { Address, Transaction } from 'viem'\nimport { lukso } from 'viem/chains'\nimport { decodeTransaction } from '../decoder/decodeTransaction'\nimport { defaultPlugins, defaultSchemaPlugins } from '../decoder/plugins'\nimport type { DecoderOptions, DecoderResult } from '../decoder/types'\nimport type { DataKey, EnhancedInfo, IDataModel } from '../types'\nimport { collectDataKeys } from './addressCollector'\n\n/**\n * Configuration for decoder integration\n */\nexport interface DecoderIntegrationConfig {\n dataModel: IDataModel\n decoderOptions?: Partial<DecoderOptions>\n addressCache?: AddressCache\n}\n\n/**\n * External cache interface for address data\n */\nexport interface AddressCache {\n get(key: DataKey): Promise<EnhancedInfo | undefined>\n set(key: DataKey, value: EnhancedInfo): Promise<void>\n has(key: DataKey): Promise<boolean>\n delete(key: DataKey): Promise<void>\n clear(): Promise<void>\n}\n\n/**\n * Integrate the decoder with the data model\n * Handles progressive transaction enhancement and address population\n */\nexport class DecoderIntegration {\n private dataModel: IDataModel\n private decoderOptions: DecoderOptions\n private addressCache?: AddressCache\n\n constructor(config: DecoderIntegrationConfig) {\n this.dataModel = config.dataModel\n this.addressCache = config.addressCache\n\n // Set up default decoder options\n this.decoderOptions = {\n plugins: defaultPlugins,\n schemaPlugins: defaultSchemaPlugins,\n wrappers: [],\n chain: config.decoderOptions?.chain || lukso,\n ...config.decoderOptions,\n }\n }\n\n /**\n * Add and decode a transaction\n * @param transaction - Raw transaction data\n * @returns Transaction signal that updates as decoding progresses\n */\n async addAndDecodeTransaction(transaction: DecoderResult) {\n // Add transaction to data model\n const signal = this.dataModel.addTransactions(transaction)\n\n // Create fresh wrappers array for this transaction\n const transactionOptions: DecoderOptions = {\n ...this.decoderOptions,\n wrappers: [], // Fresh array for collecting wrappers in this decode hierarchy\n }\n\n // Start decoding process\n const { signal: decodingSignal } = await decodeTransaction(\n transaction,\n transactionOptions\n )\n\n // Update transaction data as decoding progresses\n effect(() => {\n const state = decodingSignal.value\n if (state.data) {\n const decodedResult = state.data as DecoderResult\n\n // Process any collected wrappers\n if (transactionOptions.wrappers.length > 0) {\n // Only certain result types support wrappers\n if (\n 'wrappers' in decodedResult &&\n typeof decodedResult === 'object'\n ) {\n ;(decodedResult as Record<string, unknown>).wrappers =\n transactionOptions.wrappers\n }\n\n // Extract addresses from wrappers\n for (const wrapper of transactionOptions.wrappers) {\n this.updateAddressesFromDecoded(wrapper as DecoderResult)\n }\n }\n\n // Flatten nested batch transactions if configured\n const processedResult = this.flattenBatchTransactions(decodedResult)\n\n if (transaction.hash) {\n this.dataModel.updateTransactionData(\n transaction.hash,\n processedResult,\n 0 // decoder index\n )\n }\n\n // Extract and update addresses from decoded data\n this.updateAddressesFromDecoded(processedResult)\n }\n })\n\n return signal\n }\n\n /**\n * Add and decode multiple transactions\n * @param transactions - Array of raw transactions\n * @returns Array of transaction signals\n */\n async addAndDecodeTransactions(transactions: DecoderResult[]) {\n // Add all transactions to data model\n const signals = this.dataModel.addTransactions(transactions)\n\n // Start decoding for each transaction\n const decodingPromises = transactions.map(async (tx, index) => {\n // Create fresh wrappers array for each transaction\n const transactionOptions: DecoderOptions = {\n ...this.decoderOptions,\n wrappers: [], // Fresh array for collecting wrappers in this decode hierarchy\n }\n\n const { signal: decodingSignal } = await decodeTransaction(\n tx,\n transactionOptions\n )\n\n // Update transaction data as decoding progresses\n effect(() => {\n const state = decodingSignal.value\n if (state.data) {\n const decodedResult = state.data as DecoderResult\n\n // Process any collected wrappers\n if (transactionOptions.wrappers.length > 0) {\n // Only certain result types support wrappers\n if (\n 'wrappers' in decodedResult &&\n typeof decodedResult === 'object'\n ) {\n ;(decodedResult as Record<string, unknown>).wrappers =\n transactionOptions.wrappers\n }\n\n // Extract addresses from wrappers\n for (const wrapper of transactionOptions.wrappers) {\n this.updateAddressesFromDecoded(wrapper as DecoderResult)\n }\n }\n\n // Flatten nested batch transactions if configured\n const processedResult = this.flattenBatchTransactions(decodedResult)\n\n if (tx.hash) {\n this.dataModel.updateTransactionData(\n tx.hash,\n processedResult,\n 0 // decoder index\n )\n }\n\n // Extract and update addresses from decoded data\n this.updateAddressesFromDecoded(processedResult)\n }\n })\n\n return decodingSignal\n })\n\n await Promise.all(decodingPromises)\n return signals\n }\n\n /**\n * Extract and register addresses from decoded transaction data\n */\n private async updateAddressesFromDecoded(decodedData: DecoderResult) {\n const addresses = collectDataKeys(decodedData)\n\n // Check cache and inject into data model\n for (const address of addresses) {\n // Check cache first\n if (this.addressCache) {\n const cached = await this.addressCache.get(address)\n if (cached) {\n // Inject into data model\n this.dataModel.updateData(cached)\n }\n }\n\n // Ensure the address signal exists (creates empty signal if not)\n // This allows views to getAddress() without errors\n this.dataModel.getAddress(address)\n }\n }\n\n /**\n * Flatten nested batch transactions\n * If a batch contains another batch as a child, flatten all sub-transactions into the parent's children\n *\n * Structure:\n * - Wrappers: The \"invisible\" execute functions (execute, executeRelayCall, etc.) that wrap the actual transaction\n * - Children: The actual transactions being executed\n *\n * Result:\n * - Single transaction: { resultType: 'execute', wrappers: [...] }\n * - Batch transaction: { resultType: 'executeBatch', children: [flat list], wrappers: [...] }\n *\n * This ensures only ONE level of batch with all transactions flattened\n */\n private flattenBatchTransactions(result: DecoderResult): DecoderResult {\n // Only process batch result types\n if (\n result.resultType !== 'executeBatch' &&\n result.resultType !== 'setDataBatch'\n ) {\n return result\n }\n\n // Type guard to ensure we have children property\n if (!('children' in result) || !Array.isArray(result.children)) {\n return result\n }\n\n // Flatten children - if any child is also a batch, merge its children up\n const flattenedChildren: unknown[] = []\n\n for (const child of result.children) {\n if (typeof child === 'object' && child && 'resultType' in child) {\n const childResult = child as Record<string, unknown>\n if (\n childResult.resultType === 'executeBatch' ||\n childResult.resultType === 'setDataBatch'\n ) {\n // This child is also a batch - flatten its children into our array\n if (\n 'children' in childResult &&\n Array.isArray(childResult.children)\n ) {\n flattenedChildren.push(...childResult.children)\n }\n } else {\n // Regular child - keep as is\n flattenedChildren.push(child)\n }\n }\n }\n\n // Return updated result with flattened children\n return {\n ...result,\n children: flattenedChildren,\n } as DecoderResult\n }\n\n /**\n * Load missing address data\n * This would be called by an external service that fetches address data\n */\n async loadAddressData(addressData: EnhancedInfo[]) {\n // Update data model\n this.dataModel.injectData(addressData)\n\n // Update cache if available\n if (this.addressCache) {\n await Promise.all(\n addressData.map((data) => {\n const key: DataKey = data.tokenId\n ? (`${data.address}:${data.tokenId}` as DataKey)\n : (data.address as DataKey)\n return this.addressCache?.set(key, data) ?? Promise.resolve()\n })\n )\n }\n }\n\n /**\n * Get addresses that need to be fetched\n */\n getMissingAddresses(): DataKey[] {\n return this.dataModel.getMissingKeys()\n }\n\n /**\n * Get addresses currently being loaded\n */\n getLoadingAddresses(): DataKey[] {\n return this.dataModel.getLoadingKeys()\n }\n}\n\n/**\n * Create a simple in-memory address cache\n */\nexport function createMemoryAddressCache(): AddressCache {\n const cache = new Map<string, EnhancedInfo>()\n\n return {\n async get(key: DataKey) {\n return cache.get(key)\n },\n async set(key: DataKey, value: EnhancedInfo) {\n cache.set(key, value)\n },\n async has(key: DataKey) {\n return cache.has(key)\n },\n async delete(key: DataKey) {\n cache.delete(key)\n },\n async clear() {\n cache.clear()\n },\n }\n}\n","import type { Address, Chain } from 'viem'\nimport {\n bytesToHex,\n decodeAbiParameters,\n isHex,\n parseAbiParameters,\n} from 'viem'\n\n/**\n * LSP23 Factory address (same on all networks)\n */\nexport const LSP23_FACTORY_ADDRESS =\n '0x2300000a84d25df63081feaa37ba6b62c4c89a30' as const\n\n/**\n * deployERC1167Proxies function selector\n */\nexport const DEPLOY_ERC1167_PROXIES_SELECTOR = '0x6a66a753' as const\n\n/**\n * LSP23 deployment data structure\n */\nexport interface LSP23DeploymentData {\n profileAddress: Address\n urdAddress: Address\n deployerAddress: Address // The controller that deployed this profile\n salt: string\n primaryImplementation: Address\n secondaryImplementation: Address\n postDeploymentModule: Address\n initializationCalldata: string\n deploymentCalldata: string // Full calldata to deployERC1167Proxies\n transactionHash: string\n blockNumber: bigint\n blockTimestamp: number // Unix timestamp of the block\n chainId: number\n}\n\n/**\n * Contract deployment tuple structures\n * Primary: (bytes32 salt, uint256 fundingAmount, address implementationContract, bytes initializeCalldata)\n * Secondary: (uint256 fundingAmount, address implementationContract, bytes addInitializeCalldata, bool addConstructor, bytes constructorParams)\n */\n\n/**\n * Decode deployERC1167Proxies calldata\n *\n * Function signature:\n * deployERC1167Proxies(\n * (bytes32 salt, uint256 fundingAmount, address implementationContract, bytes initializeCalldata) primaryContractDeployment,\n * (uint256 fundingAmount, address implementationContract, bytes addInitializeCalldata, bool addConstructor, bytes constructorParams) secondaryContractDeployment,\n * address postDeploymentModule,\n * bytes postDeploymentModuleCalldata\n * )\n */\nexport function decodeDeploymentCalldata(input: string): {\n salt: string\n primaryImplementation: Address\n secondaryImplementation: Address\n postDeploymentModule: Address\n initializationCalldata: string\n} | null {\n try {\n // Remove function selector (first 4 bytes / 8 hex chars + 0x)\n const params = `0x${input.slice(10)}` as `0x${string}`\n\n // Decode the parameters\n const decoded = decodeAbiParameters(\n parseAbiParameters(\n '(bytes32,uint256,address,bytes), (uint256,address,bytes,bool,bytes), address, bytes'\n ),\n params\n )\n\n const [\n primaryDeployment,\n secondaryDeployment,\n postDeploymentModule,\n postDeploymentModuleCalldata,\n ] = decoded\n\n // Primary deployment tuple: (bytes32 salt, uint256 fundingAmount, address implementationContract, bytes initializeCalldata)\n const [salt, , primaryImplementation] = primaryDeployment as [\n string,\n bigint,\n Address,\n string,\n ]\n\n // Secondary deployment tuple: (uint256 fundingAmount, address implementationContract, bytes addInitializeCalldata, bool addConstructor, bytes constructorParams)\n const [, secondaryImplementation] = secondaryDeployment as [\n bigint,\n Address,\n string,\n boolean,\n string,\n ]\n\n if (!primaryImplementation || !secondaryImplementation) {\n return null\n }\n\n return {\n salt,\n primaryImplementation,\n secondaryImplementation,\n postDeploymentModule: postDeploymentModule as Address,\n initializationCalldata: postDeploymentModuleCalldata as string,\n }\n } catch (error) {\n console.error('Failed to decode LSP23 deployment calldata:', error)\n return null\n }\n}\n\n/**\n * Decode deployERC1167Proxies output to get deployed addresses\n *\n * Returns: (address primaryContractAddress, address secondaryContractAddress)\n */\nexport function decodeDeploymentOutput(output: string): {\n profileAddress: Address\n urdAddress: Address\n} | null {\n try {\n const decoded = decodeAbiParameters(\n parseAbiParameters('address, address'),\n output as `0x${string}`\n )\n\n return {\n profileAddress: decoded[0],\n urdAddress: decoded[1],\n }\n } catch (error) {\n console.error('Failed to decode LSP23 deployment output:', error)\n return null\n }\n}\n\n/**\n * Extract controller addresses from initialization calldata\n *\n * The initializationCalldata contains a setDataBatch call that sets up controller permissions.\n * Function: setDataBatch(bytes32[] dataKeys, bytes[] dataValues)\n *\n * The dataKeys contain entries like:\n * - AddressPermissions:Permissions:<controller-address>\n *\n * We extract controller addresses from these keys.\n */\nexport function extractControllersFromInitCalldata(\n initializationCalldata: string\n): Address[] {\n try {\n if (!initializationCalldata || initializationCalldata === '0x') {\n return []\n }\n\n // The postDeploymentModuleCalldata is raw ABI-encoded (bytes32[], bytes[])\n // No function selector - decode directly\n const decoded = decodeAbiParameters(\n parseAbiParameters('bytes32[], bytes[]'),\n initializationCalldata as `0x${string}`\n )\n\n const [dataKeys, dataValues] = decoded\n const controllers: Address[] = []\n\n // Look for AddressPermissions[] keys\n // The key is 0xdf30dba06db6a30e65354d9a64c60986 followed by zeros\n // The controller address is in the corresponding value at the same index (encoded as bytes)\n const ADDRESS_PERMISSIONS_ARRAY_PREFIX =\n '0xdf30dba06db6a30e65354d9a64c60986'\n\n for (let i = 0; i < dataKeys.length; i++) {\n const keyStr = dataKeys[i].toLowerCase()\n if (keyStr.startsWith(ADDRESS_PERMISSIONS_ARRAY_PREFIX)) {\n // The value contains the controller address\n const value = dataValues[i]\n\n // Convert to hex if it's not already\n const valueHex = isHex(value) ? value : bytesToHex(value as Uint8Array)\n\n // The value should be a 20-byte address (40 hex chars + 0x = 42 total)\n // or possibly 32 bytes with padding\n if (valueHex.length === 42) {\n // Exactly 20 bytes - this is the address\n const addr = valueHex as Address\n if (\n addr !== '0x0000000000000000000000000000000000000000' &&\n !controllers.some((c) => c.toLowerCase() === addr.toLowerCase())\n ) {\n controllers.push(addr)\n }\n }\n }\n }\n\n return controllers\n } catch (error) {\n console.error('Failed to extract controllers from init calldata:', error)\n return []\n }\n}\n\n/**\n * Hypersync query configuration for LSP23 deployments\n */\nexport interface HypersyncQueryConfig {\n /**\n * Controller addresses (derived keys) that deployed profiles\n * We only want LSP23 data for profiles WE created, not imported\n */\n controllerAddresses?: Address[]\n\n /**\n * Profile addresses to query deployment data for\n * More efficient than querying by controllers when we already know the profiles\n */\n profileAddresses?: Address[]\n\n /**\n * Starting block (0 for genesis)\n */\n fromBlock?: number\n\n /**\n * Ending block (undefined for latest)\n */\n toBlock?: number\n\n /**\n * Chain ID to query\n */\n chainId: number\n}\n\n/**\n * Build Hypersync query to find LSP23 deployments\n *\n * Strategy 1 (by profileAddresses - RECOMMENDED):\n * Query CREATE2 traces where the created address matches our profile addresses.\n * Then filter transactions to LSP23 factory and verify deployer is one of our controllers.\n * This is more efficient when we already know the profile addresses from GraphQL.\n *\n * Strategy 2 (by controllerAddresses - LEGACY):\n * Query transactions TO the LSP23 factory FROM our controller addresses.\n * This scans the entire chain history for all deployments by our controllers.\n */\nexport function buildLSP23DeploymentQuery(config: HypersyncQueryConfig) {\n const {\n controllerAddresses,\n profileAddresses,\n fromBlock = 0,\n toBlock,\n chainId,\n } = config\n\n // Prefer querying by profile addresses (more efficient)\n if (profileAddresses && profileAddresses.length > 0) {\n return {\n from_block: fromBlock,\n to_block: toBlock,\n // Query CREATE2 traces where the created address is one of our profiles\n traces: [\n {\n type: ['create2'],\n to: profileAddresses.map((addr) => addr.toLowerCase()),\n },\n ],\n // Also get the transactions to verify they're to the LSP23 factory\n transactions: [\n {\n to: [LSP23_FACTORY_ADDRESS.toLowerCase()],\n },\n ],\n field_selection: {\n transaction: ['hash', 'from', 'to', 'input', 'output', 'block_number'],\n trace: ['transaction_hash', 'type', 'from', 'to'],\n block: ['number', 'timestamp'],\n },\n include_all_blocks: false,\n }\n }\n\n // Fall back to querying by controller addresses (less efficient)\n if (controllerAddresses && controllerAddresses.length > 0) {\n return {\n from_block: fromBlock,\n to_block: toBlock,\n // Query transactions to the LSP23 factory from our controllers\n transactions: [\n {\n from: controllerAddresses.map((addr) => addr.toLowerCase()),\n to: [LSP23_FACTORY_ADDRESS.toLowerCase()],\n },\n ],\n // Also get traces to see the CREATE2 operations\n traces: [\n {\n type: ['create2'],\n // No filter on 'to' - we'll match by transaction hash\n },\n ],\n field_selection: {\n transaction: ['hash', 'from', 'to', 'input', 'output', 'block_number'],\n trace: ['transaction_hash', 'type', 'from', 'to'],\n block: ['number', 'timestamp'],\n },\n include_all_blocks: false,\n }\n }\n\n throw new Error(\n 'Either profileAddresses or controllerAddresses must be provided'\n )\n}\n\n/**\n * Parse Hypersync response to extract LSP23 deployment data\n * @param response - Hypersync API response\n * @param chainId - Chain ID\n * @param controllerAddresses - Optional list of controller addresses to filter by (only return deployments from these deployers)\n */\nexport function parseLSP23DeploymentsFromHypersync(\n response: any,\n chainId: number,\n controllerAddresses?: Address[]\n): LSP23DeploymentData[] {\n const deployments: LSP23DeploymentData[] = []\n\n if (!response?.data) {\n return deployments\n }\n\n // Build a map of block number -> timestamp\n const blockTimestamps = new Map<number, number>()\n for (const block of response.data.blocks || []) {\n blockTimestamps.set(block.number, block.timestamp)\n }\n\n // Build a map of transaction hash -> transaction data\n const txMap = new Map<string, any>()\n for (const tx of response.data.transactions || []) {\n if (\n tx.to?.toLowerCase() === LSP23_FACTORY_ADDRESS.toLowerCase() &&\n tx.input?.startsWith(DEPLOY_ERC1167_PROXIES_SELECTOR)\n ) {\n txMap.set(tx.hash.toLowerCase(), tx)\n }\n }\n\n // Process traces to find CREATE2 operations\n const create2Traces = new Map<string, Address>() // txHash -> created profile address\n\n for (const trace of response.data.traces || []) {\n if (trace.type === 'create2' && trace.to) {\n create2Traces.set(\n trace.transaction_hash.toLowerCase(),\n trace.to as Address\n )\n }\n }\n\n // Create a Set of lowercase controller addresses for efficient filtering\n const controllerSet = controllerAddresses\n ? new Set(controllerAddresses.map((addr) => addr.toLowerCase()))\n : null\n\n // Match transactions with traces\n for (const [txHash, profileAddress] of create2Traces) {\n const tx = txMap.get(txHash)\n if (!tx) continue\n\n // If controller filtering is enabled, verify the deployer is one of our controllers\n if (controllerSet && !controllerSet.has(tx.from.toLowerCase())) {\n continue\n }\n\n // Decode the transaction\n const decodedInput = decodeDeploymentCalldata(tx.input)\n const decodedOutput = tx.output ? decodeDeploymentOutput(tx.output) : null\n\n if (!decodedInput || !decodedOutput) continue\n\n // Get block timestamp for this transaction\n const blockTimestamp = blockTimestamps.get(tx.block_number) || 0\n\n deployments.push({\n profileAddress: decodedOutput.profileAddress,\n urdAddress: decodedOutput.urdAddress,\n deployerAddress: tx.from as Address, // The controller that deployed this profile\n salt: decodedInput.salt,\n primaryImplementation: decodedInput.primaryImplementation,\n secondaryImplementation: decodedInput.secondaryImplementation,\n postDeploymentModule: decodedInput.postDeploymentModule,\n initializationCalldata: decodedInput.initializationCalldata,\n deploymentCalldata: tx.input, // Full calldata to deployERC1167Proxies\n transactionHash: tx.hash,\n blockNumber: BigInt(tx.block_number),\n blockTimestamp, // Unix timestamp of the block\n chainId,\n })\n }\n\n return deployments\n}\n\n/**\n * Note: Hypersync querying should be done server-side to protect HYPERSYNC_TOKEN.\n * Use the wallet-app API endpoint /api/lsp23Deployments instead of calling Hypersync directly.\n *\n * This module exports:\n * - buildLSP23DeploymentQuery() - Build the Hypersync query structure\n * - parseLSP23DeploymentsFromHypersync() - Parse Hypersync response\n * - decodeDeploymentCalldata() - Decode LSP23 transaction input\n * - decodeDeploymentOutput() - Decode LSP23 transaction output\n */\n","/**\n * JSON serializer/deserializer that preserves BigInt types\n *\n * This implementation uses an 'n' suffix to indicate BigInt values,\n * ensuring that values that were originally BigInt remain BigInt,\n * and values that were originally numbers remain numbers.\n *\n * Example:\n * - BigInt(123) serializes to \"123n\"\n * - Number(123) serializes to 123\n *\n * This is important for blockchain data where some values must be BigInt\n * (e.g., gas, value, nonce) while others should remain as numbers\n * (e.g., array indices, status codes).\n */\n\nexport const JSONbigString = {\n /**\n * Stringify an object, converting BigInt values to strings with 'n' suffix\n */\n stringify: (obj: any, replacer?: any, space?: string | number): string => {\n return JSON.stringify(\n obj,\n (key, value) => {\n if (typeof value === 'bigint') {\n return value.toString() + 'n'\n }\n return value\n },\n space\n )\n },\n\n /**\n * Parse a JSON string, converting strings ending with 'n' back to BigInt\n */\n parse: (text: string): any => {\n return JSON.parse(text, (key, value) => {\n if (typeof value === 'string' && /^\\d+n$/.test(value)) {\n return BigInt(value.slice(0, -1))\n }\n return value\n })\n },\n}\n\nexport default JSONbigString\n","/**\n * @lukso/decoder - Consumer API\n *\n * This is the main entry point for consumers of the decoder.\n * Import data provider functions from '@lukso/transaction-decoder/data' instead.\n */\n\nimport { consumerModel, createGlobalInstance } from './core/instance'\n\n// Export all types that consumers need\nexport type {\n AddressState,\n DataKey,\n EnhancedInfo,\n IDataModelConsumer,\n TransactionState,\n} from './types'\n// DecoderResult is exported from decoder/types via the decoder imports below\n\n// Export all consumer methods directly\nexport const getTransaction = consumerModel.getTransaction.bind(consumerModel)\nexport const getTransactionByKey =\n consumerModel.getTransactionByKey.bind(consumerModel)\nexport const getTransactionsByIndex =\n consumerModel.getTransactionsByIndex.bind(consumerModel)\nexport const getTransactionHashByIndex =\n consumerModel.getTransactionHashByIndex.bind(consumerModel)\nexport const getTransactionCount =\n consumerModel.getTransactionCount.bind(consumerModel)\nexport const getDecodedCount = consumerModel.getDecodedCount.bind(consumerModel)\nexport const getDecodedTransactions =\n consumerModel.getDecodedTransactions.bind(consumerModel)\nexport const getTransactionsInOrder =\n consumerModel.getTransactionsInOrder.bind(consumerModel)\n\n// Address methods\nexport const getAddress = consumerModel.getAddress.bind(consumerModel)\nexport const getSignal = consumerModel.getSignal.bind(consumerModel)\nexport const subscribe = consumerModel.subscribe.bind(consumerModel)\nexport const getState = consumerModel.getState.bind(consumerModel)\nexport const hasData = consumerModel.hasData.bind(consumerModel)\nexport const getData = consumerModel.getData.bind(consumerModel)\nexport const isLoading = consumerModel.isLoading.bind(consumerModel)\nexport const getError = consumerModel.getError.bind(consumerModel)\n\n// Collection methods\nexport const getAllKeys = consumerModel.getAllKeys.bind(consumerModel)\nexport const getAllData = consumerModel.getAllData.bind(consumerModel)\nexport const getAllTransactions =\n consumerModel.getAllTransactions.bind(consumerModel)\n\n// Also export the consumer model instance for advanced usage\nexport { consumerModel }\n\n// Export the function to create global instance (for manual setup)\nexport { createGlobalInstance }\n\n// Export client utilities\nexport {\n createApiAddressResolver,\n type ResolveAddressesOptions,\n type ResolveAddressesResponse,\n resolveAddresses,\n} from './client/resolveAddresses'\n// Export address collection utilities from core\nexport { collectDataKeys } from './core/addressCollector'\nexport {\n AddressResolver,\n type AddressResolverConfig,\n} from './core/addressResolver'\n// Export integration classes\nexport {\n type AddressCache,\n createMemoryAddressCache,\n DecoderIntegration,\n type DecoderIntegrationConfig,\n} from './core/integrateDecoder'\n// Export aggregation utilities\nexport {\n type AggregationState,\n PluginAggregationEngine,\n standardAggregation,\n} from './decoder/aggregation'\nexport type {\n AddressResolver as TransactionAddressResolver,\n TransactionDecoderResult,\n} from './decoder/decodeTransaction'\n// Export decoder integration utilities\nexport {\n decodeTransaction,\n decodeTransactionAsync,\n} from './decoder/decodeTransaction'\n// Export plugin development utilities\n// Export default plugins to ensure they're imported and register themselves\nexport {\n createAggregationKey,\n defaultPlugins,\n defaultSchemaPlugins,\n standardPlugin,\n standardSchemaPlugin,\n} from './decoder/plugins'\nexport type {\n PluginMetadata,\n SchemaPluginMetadata,\n} from './decoder/registry'\nexport {\n createNamedPlugin,\n createNamedSchemaPlugin,\n pluginRegistry,\n registerPlugin,\n registerSchemaPlugin,\n} from './decoder/registry'\nexport type {\n Aggregation,\n DecodeEventCallback,\n DecodeEventResult,\n DecoderPlugin,\n DecoderResult,\n EnhancerCallback,\n PluginOptions,\n ResultAggregate,\n ResultCreate,\n ResultError,\n ResultExecute,\n ResultExecuteBatch,\n ResultFollowProfile,\n ResultGrafitti,\n ResultRaw,\n ResultSetData,\n ResultSetDataBatch,\n ResultWrapper,\n SchemaPlugin,\n} from './decoder/types'\n// Export utility functions\nexport { getArgByName, needsEnhancement } from './decoder/utils'\n// Export LSP23 deployment resolver utilities\n// Note: Actual Hypersync querying should be done via wallet-app API to protect HYPERSYNC_TOKEN\nexport {\n buildLSP23DeploymentQuery,\n DEPLOY_ERC1167_PROXIES_SELECTOR,\n decodeDeploymentCalldata,\n decodeDeploymentOutput,\n extractControllersFromInitCalldata,\n type HypersyncQueryConfig,\n LSP23_FACTORY_ADDRESS,\n type LSP23DeploymentData,\n parseLSP23DeploymentsFromHypersync,\n} from './server/lsp23Resolver'\n// Export shared address resolver utilities\nexport {\n type AssetData,\n fetchMultipleAddresses,\n fetchProfilesByControllers,\n getGraphQLEndpoint,\n getImage,\n type ImageData,\n type ImageURL,\n type LinkData,\n type ProfileData,\n type TFetchAddressData,\n type TokenData,\n} from './shared/addressResolver'\n// Export cache utilities\nexport {\n type AddressIdentityCache,\n createMemoryAddressIdentityCache,\n dataKeyToString,\n getDataKeyCacheKey,\n parseDataKey,\n} from './shared/cache'\n// Export debug utility for edge/worker environments\nexport { createDebug } from './utils/debug'\n// Export JSON BigInt serializer/deserializer\nexport { JSONbigString } from './utils/json-bigint'\n// Release update\n// build 1\n"],"mappings":"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","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  __name
3
- } from "./chunk-T4H2HHIB.js";
3
+ } from "./chunk-XVHJWV5U.js";
4
4
 
5
5
  // src/shared/addressResolver.ts
6
6
  import request, { gql } from "graphql-request";
@@ -202,7 +202,7 @@ async function fetchMultipleAddresses(addresses, graphqlEndpoint, cache) {
202
202
  }
203
203
  if (data.Token) {
204
204
  for (const token of data.Token) {
205
- const { id: _id, baseAsset, tokenId, ...rest } = token;
205
+ const { id, baseAsset, tokenId, ...rest } = token;
206
206
  if (baseAsset?.id && tokenId) {
207
207
  const enhancedInfo = {
208
208
  address: baseAsset.id,
@@ -366,7 +366,7 @@ async function getImage(images, options) {
366
366
  return options.fallback ? { src: options.fallback, width: 128, height: 128 } : void 0;
367
367
  }
368
368
  try {
369
- let isImage;
369
+ let isImage = void 0;
370
370
  if (typeof caches !== "undefined" && !ignoreHead) {
371
371
  const cache = await caches.open("image-types");
372
372
  const cached = await cache.match(url);
@@ -378,7 +378,7 @@ async function getImage(images, options) {
378
378
  }
379
379
  }
380
380
  if (!isImage && !ignoreHead) {
381
- const _now = Date.now();
381
+ const now = Date.now();
382
382
  isImage = await fetch(url, { method: "HEAD" }).then((response) => {
383
383
  if (response.ok) {
384
384
  const mime = response.headers.get("content-type") || "";
@@ -434,4 +434,4 @@ export {
434
434
  fetchProfilesByControllers,
435
435
  getImage
436
436
  };
437
- //# sourceMappingURL=chunk-FKBKAWB3.js.map
437
+ //# sourceMappingURL=chunk-GGBHTWJL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/shared/addressResolver.ts"],"sourcesContent":["import request, { gql } from 'graphql-request'\nimport type { Address, Chain, Hex } from 'viem'\nimport { lukso } from 'viem/chains'\nimport type { DataKey, EnhancedInfo } from '../types'\nimport type { AddressIdentityCache } from './cache'\n\n/**\n * GraphQL queries for address resolution\n * Using the exact schema from addressGQL.ts\n */\nconst addressesGql = gql`\nquery AddressQuery($profiles: [String!], $assets: [String!], $tokens: [String!]) {\n Profile(\n where: {id: {_in: $profiles}}\n ) {\n fullName\n id\n name\n tags\n description\n standard\n controllers {\n address\n tags\n permissions\n }\n owner {\n id\n }\n profileImages(where: {error: {_is_null: true}}, order_by: {width: asc}) {\n width\n height\n src\n verified\n }\n backgroundImages(where: {error: {_is_null: true}}, order_by: {width: asc}) {\n width\n height\n src\n verified\n }\n avatars(where: {error: {_is_null: true}}, order_by: {width: asc}) {\n width\n height\n src\n verified\n }\n }\n Token(where: {id: {_in: $tokens}}) {\n id\n baseAsset {\n id\n description\n icons {\n src\n verified\n width\n height\n }\n isCollection\n isLSP7\n isUnknown\n name\n standard\n interfaces\n decimals\n owner_id\n lsp4Creators {\n profile_id\n }\n }\n formattedTokenId\n icons {\n src\n verified\n width\n height\n }\n images(where: {index: {_eq: 0}}) {\n src\n verified\n width\n height\n }\n lsp4TokenName\n lsp4TokenSymbol\n lsp4TokenType\n lsp8TokenIdFormat\n tokenId\n name\n description\n lsp4Creators {\n profile_id\n }\n }\n Asset(where: {id: {_in: $assets}}) {\n id\n images(where: {index: {_eq: 0}}) {\n src\n width\n verified\n height\n }\n interfaces\n isCollection\n isLSP7\n isUnknown\n lsp4TokenName\n lsp4TokenSymbol\n lsp4TokenType\n method\n name\n icons {\n src\n width\n height\n }\n description\n decimals\n standard\n owner_id\n lsp4Creators {\n profile_id\n }\n }\n}\n`\n\n// Image data structure from GraphQL\nexport interface ImageData {\n width?: number\n height?: number\n url?: string // Raw URL (may be ipfs://)\n src?: string // Resolved HTTPS URL (fallback to url if not present)\n verified?: boolean\n}\n\n// Link data structure from GraphQL\nexport interface LinkData {\n url: string\n title?: string\n}\n\n// Profile data from GraphQL\nexport interface ProfileData {\n id: Hex\n name?: string\n fullName?: string\n tags?: string[]\n description?: string\n links?: LinkData[]\n standard?: string\n controllers?: Array<{\n address: string\n tags?: string[]\n permissions?: Hex\n }>\n owner?: { id: string }\n profileImages?: ImageData[]\n backgroundImages?: ImageData[]\n avatars?: ImageData[]\n}\n\n// Asset data from GraphQL\nexport interface AssetData {\n id: Hex\n name?: string\n standard?: string\n lsp4TokenName?: string\n lsp4TokenSymbol?: string\n lsp4TokenType?: string\n method?: string\n description?: string\n links?: LinkData[]\n decimals?: number\n interfaces?: string[]\n isCollection?: boolean\n isLSP7?: boolean\n isUnknown?: boolean\n icons?: ImageData[]\n images?: ImageData[]\n}\n\n// Token data from GraphQL\nexport interface TokenData {\n id: Hex\n tokenId?: Hex\n name?: string\n description?: string\n links?: LinkData[]\n lsp4TokenName?: string\n lsp4TokenSymbol?: string\n lsp4TokenType?: string\n lsp8TokenIdFormat?: string\n formattedTokenId?: string\n baseAsset?: {\n id: Hex\n description?: string\n icons?: ImageData[]\n isCollection?: boolean\n isLSP7?: boolean\n isUnknown?: boolean\n name?: string\n standard?: string\n interfaces?: string[]\n decimals?: number\n }\n icons?: ImageData[]\n images?: ImageData[]\n}\n\nexport type TFetchAddressData = {\n Profile?: ProfileData[]\n Asset?: AssetData[]\n Token?: TokenData[]\n}\n\n/**\n * Fetch multiple addresses from GraphQL and return them as a Map\n * This is the shared implementation that both server and core can use\n */\nexport async function fetchMultipleAddresses(\n addresses: readonly DataKey[],\n graphqlEndpoint: string,\n cache?: AddressIdentityCache\n): Promise<Map<DataKey, EnhancedInfo>> {\n const results = new Map<DataKey, EnhancedInfo>()\n\n if (addresses.length === 0) {\n return results\n }\n\n // Check cache first if provided\n const uncachedAddresses: DataKey[] = []\n\n if (cache) {\n // Try to get many at once if supported\n if (cache.getMany) {\n const cachedResults = await cache.getMany(addresses)\n for (const [key, value] of cachedResults) {\n results.set(key, value)\n }\n // Find which ones we still need to fetch\n for (const addr of addresses) {\n if (!results.has(addr)) {\n uncachedAddresses.push(addr)\n }\n }\n } else {\n // Fall back to individual lookups\n for (const addr of addresses) {\n const cached = await cache.get(addr)\n if (cached) {\n results.set(addr, cached)\n } else {\n uncachedAddresses.push(addr)\n }\n }\n }\n\n // If all were cached, return early\n if (uncachedAddresses.length === 0) {\n return results\n }\n } else {\n // No cache, fetch all\n uncachedAddresses.push(...addresses)\n }\n\n // Parse addresses and tokens\n const profiles: string[] = []\n const assets: string[] = []\n const tokens: string[] = []\n const tokenMapping = new Map<string, { address: Address; tokenId: string }>()\n\n for (const key of uncachedAddresses) {\n const hasDash = key.includes('-')\n const hasColon = key.includes(':')\n\n if (hasColon || hasDash) {\n const normalizedKey = key.replace(/[-:]/, '-')\n tokens.push(normalizedKey)\n const [address, tokenId] = key.split(/[-:]/)\n tokenMapping.set(key, { address: address as Address, tokenId })\n } else {\n // Regular addresses - could be profiles or assets\n profiles.push(key)\n assets.push(key)\n }\n }\n\n try {\n // Fetch data from GraphQL\n const data = (await request(graphqlEndpoint, addressesGql, {\n profiles,\n assets,\n tokens,\n })) as TFetchAddressData\n\n // Process profiles\n if (data.Profile) {\n for (const profile of data.Profile) {\n if (profile.standard !== 'LSP0ERC725Account') {\n continue\n }\n const enhancedInfo: EnhancedInfo = {\n address: profile.id as Address,\n __gqltype: 'Profile',\n name: profile.name || profile.fullName,\n fullName: profile.fullName,\n standard: profile.standard,\n tags: profile.tags,\n description: profile.description,\n owner: profile.owner,\n controllers: profile.controllers,\n profileImages: profile.profileImages,\n backgroundImages: profile.backgroundImages,\n avatars: profile.avatars,\n }\n results.set(profile.id as Address, enhancedInfo)\n }\n }\n\n // Process tokens (must be before assets per addressGQL.ts logic)\n if (data.Token) {\n for (const token of data.Token) {\n const { id, baseAsset, tokenId, ...rest } = token\n\n // Tokens have a composite ID format and baseAsset reference\n if (baseAsset?.id && tokenId) {\n const enhancedInfo: EnhancedInfo = {\n address: baseAsset.id as Address,\n tokenId: tokenId as Address,\n __gqltype: 'Token',\n ...rest,\n baseAsset,\n }\n // Store with both dash and colon separators to handle both formats\n const keyWithColon = `${baseAsset.id}:${tokenId}` as DataKey\n const keyWithDash = `${baseAsset.id}-${tokenId}` as DataKey\n results.set(keyWithColon, enhancedInfo)\n results.set(keyWithDash, enhancedInfo)\n }\n }\n }\n\n // Process assets\n if (data.Asset) {\n for (const asset of data.Asset) {\n if (asset.standard === 'LSP0ERC725Account') {\n // Skip profiles - already processed\n continue\n }\n const enhancedInfo: EnhancedInfo = {\n address: asset.id as Address,\n __gqltype: 'Asset',\n ...asset,\n }\n if (!results.has(asset.id as Address)) {\n results.set(asset.id as Address, enhancedInfo)\n }\n }\n }\n\n // Cache the newly fetched results\n if (cache) {\n const newEntries: Array<[DataKey, EnhancedInfo]> = []\n\n // Collect all new entries\n for (const [key, value] of results) {\n // Only cache entries that were fetched (not from cache)\n const isCached = addresses.some(\n (addr) => addr.toLowerCase() === key.toLowerCase()\n )\n\n if (\n isCached &&\n uncachedAddresses.some(\n (addr) => addr.toLowerCase() === key.toLowerCase()\n )\n ) {\n newEntries.push([key, value])\n }\n }\n\n // Use batch update if available\n if (cache.setMany && newEntries.length > 0) {\n await cache.setMany(newEntries)\n } else {\n // Fall back to individual updates\n for (const [key, value] of newEntries) {\n await cache.set(key, value)\n }\n }\n }\n\n return results\n } catch (error) {\n console.error('Failed to fetch addresses:', error)\n return results\n }\n}\n\n/**\n * Get GraphQL endpoint for a given chain\n */\nexport function getGraphQLEndpoint(chain: Chain): string {\n return chain.id === lukso.id\n ? 'https://envio.lukso-mainnet.universal.tech/v1/graphql'\n : 'https://envio.lukso-testnet.universal.tech/v1/graphql'\n}\n\n/**\n * GraphQL query to find profiles controlled by specific addresses\n */\nconst profilesByControllerGql = gql`\nquery ProfilesByController($controllerAddresses: [String!]) {\n Profile(\n where: {\n controllers: {\n address: { _in: $controllerAddresses }\n tags: {\n _contains: [\n \"ADDCONTROLLER\"\n \"EDITPERMISSIONS\"\n \"SUPER_TRANSFERVALUE\"\n \"TRANSFERVALUE\"\n \"SUPER_CALL\"\n \"CALL\"\n \"SUPER_STATICCALL\"\n \"STATICCALL\"\n \"DEPLOY\"\n \"SUPER_SETDATA\"\n \"SETDATA\"\n \"ENCRYPT\"\n \"DECRYPT\"\n \"SIGN\"\n \"EXECUTE_RELAY_CALL\"\n ]\n }\n }\n }\n order_by: { blockNumber: asc }\n ) {\n fullName\n id\n name\n tags\n description\n standard\n controllers {\n address\n tags\n permissions\n }\n owner {\n id\n }\n profileImages(where: {error: {_is_null: true}}, order_by: {width: asc}) {\n width\n height\n src\n verified\n }\n backgroundImages(where: {error: {_is_null: true}}, order_by: {width: asc}) {\n width\n height\n src\n verified\n }\n avatars(where: {error: {_is_null: true}}, order_by: {width: asc}) {\n width\n height\n src\n verified\n }\n }\n}\n`\n\n/**\n * Find profiles controlled by specific controller addresses\n * @param controllerAddresses - Array of controller addresses to search for\n * @param chain - Which chain to query\n * @returns Array of profile data\n */\nexport async function fetchProfilesByControllers(\n controllerAddresses: readonly Address[],\n chain: Chain\n): Promise<ProfileData[]> {\n const graphqlEndpoint = getGraphQLEndpoint(chain)\n\n try {\n const data = (await request(graphqlEndpoint, profilesByControllerGql, {\n controllerAddresses: controllerAddresses.map((addr) =>\n addr.toLowerCase()\n ),\n })) as { Profile?: ProfileData[] }\n\n return data.Profile || []\n } catch (error) {\n console.error(\n `Failed to fetch profiles by controllers on ${chain.name}:`,\n error\n )\n return []\n }\n}\n\nexport type ImageURL = {\n url?: string\n data?: string\n src?: string\n width: number\n height: number\n index?: number\n verified?: string\n}\n\n/**\n * Assuming the images are sorted ascending by width and/or height pick the first\n * image that's larger than the requested size * dpr and process that one.\n * By default this will assume the data came from the indexer and therefore\n * we do not need to verify the existence of all the images (i.e. HEAD requests for\n * each image) Setting ignoreHead to false is important during RPC mode so that\n * we can skip images that are not really available.\n *\n * @param images - array of images\n * @param options - specify arguments for search/processing\n * @returns { width, height, src } - the image that fits the criteria\n */\nexport async function getImage(\n images: ImageURL[],\n options: {\n width: number\n height?: number\n index?: number\n ignoreVerification?: boolean\n forcePng?: boolean\n ignoreHead?: boolean\n fallback?: string\n dpr?: number\n }\n): Promise<{ width: number; height: number; src?: string } | undefined> {\n const {\n width,\n height: _height,\n index,\n ignoreVerification,\n ignoreHead = true, // By default we don't want to do HEAD requests for all images.\n dpr = 1,\n } = options\n const boost = dpr === 1 ? 1.5 : 1\n const height = _height || width\n const { src: _src, verified } =\n (images || []).find(\n (i) =>\n i.width >= width * boost * dpr &&\n i.height &&\n i.height >= height * boost * dpr &&\n (index ? i.index === index : i.index === undefined)\n ) ||\n images?.at(-1) ||\n {}\n // We're talking about images here, so we should be using /image/ instead of /ipfs/\n const url = _src?.startsWith('https://api.universalprofile.cloud/ipfs/')\n ? _src?.replace(/\\/ipfs\\//, '/image/')\n : _src\n if (!url) {\n return options.fallback\n ? { src: options.fallback, width: 128, height: 128 }\n : undefined\n }\n try {\n let isImage: string | undefined = undefined\n if (typeof caches !== 'undefined' && !ignoreHead) {\n const cache = await caches.open('image-types')\n const cached = await cache.match(url)\n if (cached) {\n const response = await cached.json()\n if (response) {\n isImage = response\n }\n }\n }\n if (!isImage && !ignoreHead) {\n // HEAD will return 200, 404 and so including the 'content-type'\n // We use this to determine what type of images we have.\n // If the images came from the indexer then this test\n // has already been done on the indexer and we can skip it here.\n const now = Date.now()\n isImage = await fetch(url, { method: 'HEAD' })\n .then((response) => {\n if (response.ok) {\n const mime = response.headers.get('content-type') || ''\n response.body?.cancel()\n return /^image\\//.test(mime) ? mime : undefined\n }\n response.body?.cancel()\n return undefined\n })\n .catch((error) => {\n console.error((error as Error).stack)\n return undefined\n })\n if (isImage != null && typeof caches !== 'undefined') {\n const cache = await caches.open('image-types')\n await cache\n .put(url, new Response(JSON.stringify(isImage)))\n .catch((error) => {\n console.error((error as Error).stack, url)\n })\n }\n }\n if (isImage || ignoreHead) {\n const finalUrl = new URL(url)\n const { searchParams } = finalUrl\n const qs = new URLSearchParams(searchParams)\n if (width) {\n qs.set('width', `${width * boost}`)\n }\n if (width || height) {\n qs.set('height', `${(height || width) * boost}`)\n }\n qs.set('fit', 'cover')\n qs.set('dpr', dpr.toString())\n if (\n !options.ignoreHead &&\n !/\\/svg/.test(isImage || '') &&\n options.forcePng\n ) {\n qs.set('format', 'png')\n }\n finalUrl.search = qs.toString()\n const image = finalUrl.toString()\n return {\n width,\n height: height || width,\n src:\n verified === 'INVALID' && !ignoreVerification\n ? `${image}&blur=30`\n : image,\n }\n }\n } catch (error) {\n console.error((error as Error).stack)\n }\n return options.fallback\n ? { src: options.fallback, width: 128, height: 128 }\n : undefined\n}\n"],"mappings":"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","names":[]}
@@ -4,11 +4,11 @@ import {
4
4
  decodeTransaction,
5
5
  isAsyncOperationEnabled,
6
6
  pluginRegistry
7
- } from "./chunk-T4H2HHIB.js";
7
+ } from "./chunk-XVHJWV5U.js";
8
8
 
9
9
  // src/core/dataModel.ts
10
10
  import { batch, effect, signal } from "@preact/signals-core";
11
- import { isHex, size } from "viem";
11
+ import { hexToBigInt, isHex, size, slice } from "viem";
12
12
  function deepFreeze(obj) {
13
13
  if (obj === null || typeof obj !== "object" || Object.isFrozen(obj)) {
14
14
  return obj;
@@ -39,6 +39,30 @@ var DataModel = class {
39
39
  constructor(options = {}) {
40
40
  this.options = options;
41
41
  }
42
+ /**
43
+ * Extract a 20-byte address from a potentially 32-byte hex value
44
+ * If the input is 32 bytes, validates it's zero-padded and takes the rightmost 20 bytes
45
+ * If the input is 20 bytes, returns it as-is
46
+ */
47
+ extractAddress(hex) {
48
+ if (!isHex(hex)) {
49
+ throw new Error(`Invalid hex value: ${hex}`);
50
+ }
51
+ const bytes = size(hex);
52
+ if (bytes === 32) {
53
+ const first12Bytes = slice(hex, 0, 12);
54
+ if (hexToBigInt(first12Bytes) !== 0n) {
55
+ throw new Error(
56
+ `Invalid 32-byte address: first 12 bytes must be zero for a padded address, got ${first12Bytes}`
57
+ );
58
+ }
59
+ return slice(hex, 12, 32);
60
+ }
61
+ if (bytes === 20) {
62
+ return hex;
63
+ }
64
+ throw new Error(`Invalid address length: ${bytes} bytes`);
65
+ }
42
66
  /**
43
67
  * Get or create a signal for a specific key
44
68
  */
@@ -812,4 +836,4 @@ export {
812
836
  decodeTransaction2 as decodeTransaction,
813
837
  decodeTransactionAsync
814
838
  };
815
- //# sourceMappingURL=chunk-NDBDNXBI.js.map
839
+ //# sourceMappingURL=chunk-GXZOF3QY.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/dataModel.ts","../src/core/instance.ts","../src/decoder/decodeTransaction.ts","../src/shared/constants.ts"],"sourcesContent":["// Core data model implementation\nimport { batch, effect, type Signal, signal } from '@preact/signals-core'\nimport type { Address, Hex } from 'viem'\nimport { hexToBigInt, isHex, size, slice } from 'viem'\nimport type {\n AddressState,\n DataKey,\n DataModelOptions,\n DecoderResult,\n EnhancedInfo,\n IDataModel,\n IDataModelConsumer,\n TransactionState,\n} from '../types'\nimport { collectDataKeys } from './addressCollector'\n\n// Helper type for deep freezing - kept internal to this module\ntype DeepReadonly<T> = T extends (infer R)[]\n ? DeepReadonlyArray<R>\n : T extends (...args: unknown[]) => unknown\n ? T\n : T extends object\n ? DeepReadonlyObject<T>\n : T\n\ninterface DeepReadonlyArray<T> extends ReadonlyArray<DeepReadonly<T>> {}\n\ntype DeepReadonlyObject<T> = {\n readonly [P in keyof T]: DeepReadonly<T[P]>\n}\n\n/**\n * Deep freeze an object to prevent any modifications\n * Returns the same object if it's already frozen\n */\nexport function deepFreeze<T>(obj: T): T {\n // Primitives and already frozen objects don't need processing\n if (obj === null || typeof obj !== 'object' || Object.isFrozen(obj)) {\n return obj\n }\n\n // Freeze the object itself\n Object.freeze(obj)\n\n // Recursively freeze all properties\n for (const prop of Object.getOwnPropertyNames(obj)) {\n const value = (obj as Record<string, unknown>)[prop]\n if (value !== null && typeof value === 'object') {\n deepFreeze(value)\n }\n }\n\n return obj\n}\n\nexport interface TransactionKey {\n hash: Hex\n decoderIndex?: number // For batch transactions\n}\n\nexport class DataModel implements IDataModel {\n // Nested map structure: Address -> (TokenId | null) -> Signal\n private dataSignals = new Map<Address, Signal<AddressState>>()\n\n // Transaction signals: Hash -> (DecoderIndex | null) -> Signal\n private transactionSignals = new Map<\n Hex,\n Map<number | null, Signal<TransactionState>>\n >()\n\n // Keep track of unique transaction hashes in order\n private transactionOrder: Array<Hex> = []\n\n private options: DataModelOptions\n\n // Track pending resolved data updates\n private pendingResolvedUpdate = false\n\n constructor(options: DataModelOptions = {}) {\n this.options = options\n }\n\n /**\n * Extract a 20-byte address from a potentially 32-byte hex value\n * If the input is 32 bytes, validates it's zero-padded and takes the rightmost 20 bytes\n * If the input is 20 bytes, returns it as-is\n */\n private extractAddress(hex: Hex): Address {\n if (!isHex(hex)) {\n throw new Error(`Invalid hex value: ${hex}`)\n }\n\n const bytes = size(hex)\n\n if (bytes === 32) {\n // Check if the first 12 bytes are zeros (valid padding)\n const first12Bytes = slice(hex, 0, 12)\n if (hexToBigInt(first12Bytes) !== 0n) {\n throw new Error(\n `Invalid 32-byte address: first 12 bytes must be zero for a padded address, got ${first12Bytes}`\n )\n }\n // 32 bytes with valid padding - extract the rightmost 20 bytes\n return slice(hex, 12, 32) as Address\n }\n if (bytes === 20) {\n // 20 bytes - already a proper address\n return hex as Address\n }\n throw new Error(`Invalid address length: ${bytes} bytes`)\n }\n\n /**\n * Get or create a signal for a specific key\n */\n private getOrCreateSignal(key: DataKey): Signal<AddressState> {\n let sig = this.dataSignals.get(key)\n if (!sig) {\n sig = signal<AddressState>({\n loading: false,\n data: undefined,\n error: undefined,\n lastUpdated: undefined,\n })\n\n this.dataSignals.set(key, sig)\n\n // Notify about missing keys (for external fetching)\n if (this.options.onMissingKeys) {\n // Debounce notifications\n setTimeout(() => {\n const missing = this.getMissingKeys()\n if (missing.length > 0) {\n this.options.onMissingKeys?.(missing)\n }\n }, 0)\n }\n }\n\n return sig\n }\n\n /**\n * Extract transaction key from transaction JSON\n */\n private getTransactionKey(transaction: unknown): TransactionKey {\n if (!transaction || typeof transaction !== 'object') {\n throw new Error('Transaction must be an object')\n }\n\n const tx = transaction as Record<string, unknown>\n if (!tx.hash && !tx.transactionHash) {\n throw new Error('Transaction must have hash or transactionHash')\n }\n\n return {\n hash: (tx.hash || tx.transactionHash) as Hex,\n decoderIndex: tx.decoderIndex ? (tx.decoderIndex as number) : undefined,\n }\n }\n\n /**\n * Get or create the inner map for a transaction hash\n */\n private getOrCreateTransactionMap(\n hash: Hex\n ): Map<number | null, Signal<TransactionState>> {\n const normalizedHash = hash.toLowerCase() as Hex\n let map = this.transactionSignals.get(normalizedHash)\n if (!map) {\n map = new Map()\n this.transactionSignals.set(normalizedHash, map)\n }\n return map\n }\n\n /**\n * Add one or more transactions to the model\n * Collects all addresses from all transactions and marks them as loading\n */\n addTransactions<T extends unknown | unknown[]>(\n jsonTransactions: T\n ): T extends unknown[]\n ? Array<Signal<TransactionState>>\n : Signal<TransactionState> {\n // Normalize input to array\n const transactions = Array.isArray(jsonTransactions)\n ? jsonTransactions\n : [jsonTransactions]\n const isSingle = !Array.isArray(jsonTransactions)\n // First, collect all addresses from all transactions\n const allAddresses = new Set<string>()\n const transactionAddresses: DataKey[][] = []\n\n for (const tx of transactions) {\n const addresses = collectDataKeys(tx)\n transactionAddresses.push(addresses)\n\n // Add to set for deduplication\n for (const addr of addresses) {\n allAddresses.add(addr)\n }\n }\n\n // Convert back to DataKey array\n const uniqueAddresses = Array.from(allAddresses) as DataKey[]\n\n // Mark all addresses as loading at once\n if (uniqueAddresses.length > 0) {\n this.setLoading(uniqueAddresses)\n }\n\n // Now add each transaction\n const results = transactions.map((tx, index) => {\n const key = this.getTransactionKey(tx)\n const normalizedHash = key.hash.toLowerCase() as Hex\n const decoderIndex = key.decoderIndex || null\n\n const isNewHash = !this.transactionSignals.has(normalizedHash)\n const txMap = this.getOrCreateTransactionMap(normalizedHash)\n\n if (txMap.has(decoderIndex)) {\n throw new Error(\n `Transaction already exists: ${normalizedHash}:${decoderIndex || 0}`\n )\n }\n\n // Create frozen data once\n const frozenData = deepFreeze(\n structuredClone(tx)\n ) as unknown as DeepReadonly<DecoderResult>\n\n // Create reactive transaction with frozen data\n const sig = signal<TransactionState>({\n data: frozenData,\n loading: false,\n addresses: Object.freeze([...transactionAddresses[index]]) as DataKey[],\n error: undefined,\n lastUpdated: Date.now(),\n resolvedData: frozenData, // Start with the same frozen data\n addressesResolved: false,\n })\n\n txMap.set(decoderIndex, sig)\n\n // Track transaction order (only for new hashes)\n if (isNewHash) {\n this.transactionOrder.push(normalizedHash)\n }\n\n // Notify about new transaction\n if (this.options.onNewTransaction) {\n this.options.onNewTransaction(tx)\n }\n\n return sig\n })\n\n // Return single signal if input was single, otherwise return array\n return (isSingle ? results[0] : results) as T extends unknown[]\n ? Array<Signal<TransactionState>>\n : Signal<TransactionState>\n }\n\n /**\n * Get an existing transaction signal (returns undefined if not found)\n */\n getTransaction(\n jsonTransaction: unknown\n ): Signal<TransactionState> | undefined {\n const key = this.getTransactionKey(jsonTransaction)\n const normalizedHash = key.hash.toLowerCase() as Hex\n const decoderIndex = key.decoderIndex || null\n\n const txMap = this.transactionSignals.get(normalizedHash)\n if (!txMap) {\n return undefined\n }\n\n return txMap.get(decoderIndex)\n }\n\n /**\n * Get transaction by hash and decoder index\n */\n getTransactionByKey(\n hash: Hex,\n decoderIndex?: number\n ): Signal<TransactionState> | undefined {\n const normalizedHash = hash.toLowerCase() as Hex\n const txMap = this.transactionSignals.get(normalizedHash)\n if (!txMap) {\n return undefined\n }\n\n return txMap.get(decoderIndex || null)\n }\n\n /**\n * Update a transaction's data and re-collect addresses\n * Useful after async decoding completes\n */\n updateTransactionData(\n hash: Hex,\n newData: DecoderResult,\n decoderIndex?: number\n ): void {\n const normalizedHash = hash.toLowerCase() as Hex\n const txMap = this.transactionSignals.get(normalizedHash)\n if (!txMap) return\n\n const sig = txMap.get(decoderIndex ?? null)\n if (!sig) return\n\n // Re-collect addresses with the new decoded data\n const newAddresses = collectDataKeys(newData, true, [\n ...sig.value.addresses,\n ])\n\n // Create frozen data once\n const frozenData = deepFreeze(structuredClone(newData))\n\n // Update the signal with frozen data\n sig.value = {\n ...sig.value,\n data: frozenData,\n addresses: Object.freeze([...newAddresses]) as DataKey[],\n lastUpdated: Date.now(),\n // Start with the current data, will be enhanced when addresses load\n resolvedData: frozenData,\n addressesResolved: false,\n }\n\n // Mark any new addresses as loading\n this.setLoading(newAddresses)\n\n // Check if we can create resolved data immediately\n queueMicrotask(() => {\n this.updateResolvedTransactionData()\n })\n }\n\n /**\n * Get all decoded transactions for a hash by index (insertion order)\n */\n getTransactionsByIndex(\n index: number\n ): Map<number | null, Signal<TransactionState>> | undefined {\n if (index < 0 || index >= this.transactionOrder.length) {\n return undefined\n }\n\n const hash = this.transactionOrder[index]\n return this.transactionSignals.get(hash)\n }\n\n /**\n * Get transaction hash by index\n */\n getTransactionHashByIndex(index: number): Hex | undefined {\n return this.transactionOrder[index]\n }\n\n /**\n * Get number of unique transaction hashes\n */\n getTransactionCount(): number {\n return this.transactionOrder.length\n }\n\n /**\n * Get number of decoded transactions for a specific hash\n */\n getDecodedCount(hash: Hex): number {\n const normalizedHash = hash.toLowerCase() as Hex\n const txMap = this.transactionSignals.get(normalizedHash)\n return txMap ? txMap.size : 0\n }\n\n /**\n * Get all decoded transactions for a specific hash\n */\n getDecodedTransactions(hash: Hex): Array<Signal<TransactionState>> {\n const normalizedHash = hash.toLowerCase() as Hex\n const txMap = this.transactionSignals.get(normalizedHash)\n return txMap ? Array.from(txMap.values()) : []\n }\n\n /**\n * Get address signal (alias for getSignal for clearer API)\n */\n getAddress(address: DataKey): Signal<AddressState> {\n return this.getSignal(address)\n }\n\n /**\n * Inject data into the model\n * Can be called multiple times to progressively add/update data\n */\n injectData(dataList: EnhancedInfo[]): void {\n batch(() => {\n for (const data of dataList) {\n const key: DataKey = data.tokenId\n ? `${data.address as Hex}:${data.tokenId}`\n : (data.address as Hex)\n\n const sig = this.getOrCreateSignal(key)\n\n // Update the signal with frozen data\n sig.value = {\n loading: false,\n data: deepFreeze(structuredClone(data)),\n error: undefined,\n lastUpdated: Date.now(),\n }\n }\n })\n\n // After the batch, check if any transactions need their resolved data updated\n this.updateResolvedTransactionData()\n }\n\n /**\n * Update a single item\n */\n updateData(data: EnhancedInfo): void {\n const key: DataKey = data.tokenId\n ? `${data.address as Hex}:${data.tokenId}`\n : (data.address as Hex)\n\n const sig = this.getOrCreateSignal(key)\n\n sig.value = {\n loading: false,\n data: deepFreeze(structuredClone(data)),\n error: undefined,\n lastUpdated: Date.now(),\n }\n\n // Debounce the resolved data update using a microtask\n if (!this.pendingResolvedUpdate) {\n this.pendingResolvedUpdate = true\n queueMicrotask(() => {\n this.pendingResolvedUpdate = false\n this.updateResolvedTransactionData()\n })\n }\n }\n\n /**\n * Mark keys as loading\n */\n setLoading(keys: DataKey[]): void {\n batch(() => {\n for (const key of keys) {\n const sig = this.getOrCreateSignal(key)\n sig.value = { ...sig.value, loading: true }\n }\n })\n }\n\n /**\n * Mark a key as errored\n */\n setError(key: DataKey, error: string): void {\n const sig = this.getOrCreateSignal(key)\n sig.value = {\n loading: false,\n data: undefined,\n error,\n lastUpdated: Date.now(),\n }\n }\n\n /**\n * Get signal for a key (creates one if doesn't exist)\n */\n getSignal(key: DataKey): Signal<AddressState> {\n return this.getOrCreateSignal(key)\n }\n\n /**\n * Subscribe to key updates\n */\n subscribe(key: DataKey, callback: (state: AddressState) => void): () => void {\n const sig = this.getSignal(key)\n return effect(() => callback(sig.value))\n }\n\n /**\n * Get current state of a key\n */\n getState(key: DataKey): AddressState {\n return this.getSignal(key).value\n }\n\n /**\n * Get all keys that have no data\n */\n getMissingKeys(): DataKey[] {\n const missingKeys: DataKey[] = []\n\n for (const [key] of this.dataSignals) {\n missingKeys.push(key as Hex)\n }\n\n return missingKeys\n }\n\n /**\n * Get all keys currently loading\n */\n getLoadingKeys(): DataKey[] {\n const loadingKeys: DataKey[] = []\n\n for (const [key, sig] of this.dataSignals) {\n if (sig.value.loading) {\n loadingKeys.push(key as Hex)\n }\n }\n\n return loadingKeys\n }\n\n /**\n * Check if we have data for a key\n */\n hasData(key: DataKey): boolean {\n const sig = this.dataSignals.get(key)\n return sig ? sig.value.data !== undefined : false\n }\n\n /**\n * Clear all data\n */\n clear(): void {\n batch(() => {\n // Clear address data\n for (const sig of this.dataSignals.values()) {\n sig.value = {\n loading: false,\n data: undefined,\n error: undefined,\n lastUpdated: undefined,\n }\n }\n\n // Clear transaction data\n for (const txMap of this.transactionSignals.values()) {\n for (const sig of txMap.values()) {\n sig.value = {\n ...sig.value,\n loading: false,\n error: undefined,\n }\n }\n }\n })\n }\n\n /**\n * Remove specific keys from cache\n */\n remove(keys: DataKey[]): void {\n for (const key of keys) {\n this.dataSignals.delete(key)\n }\n }\n\n /**\n * Get all cached keys\n */\n getAllKeys(): ReadonlyArray<DataKey> {\n const keys: DataKey[] = []\n\n for (const [key] of this.dataSignals) {\n keys.push(key as Hex)\n }\n\n return Object.freeze(keys)\n }\n\n /**\n * Get all data as a plain object (for debugging/serialization)\n */\n getAllData(): Readonly<Record<string, AddressState>> {\n const result: Record<string, AddressState> = {}\n\n for (const [key, sig] of this.dataSignals) {\n result[key] = sig.value\n }\n\n return Object.freeze(result)\n }\n\n /**\n * Get all transaction data (for debugging)\n */\n getAllTransactions(): Readonly<Record<string, TransactionState>> {\n const result: Record<string, TransactionState> = {}\n\n for (const [hash, txMap] of this.transactionSignals) {\n for (const [decoderIndex, sig] of txMap) {\n const key = decoderIndex === null ? hash : `${hash}:${decoderIndex}`\n result[key] = sig.value\n }\n }\n\n return Object.freeze(result)\n }\n\n /**\n * Get all transactions in order (returns all decoded transactions grouped by hash)\n */\n getTransactionsInOrder(): Array<{\n hash: Hex\n transactions: Array<Signal<TransactionState>>\n }> {\n const result: Array<{\n hash: Hex\n transactions: Array<Signal<TransactionState>>\n }> = []\n\n for (const hash of this.transactionOrder) {\n const txMap = this.transactionSignals.get(hash)\n if (txMap) {\n result.push({\n hash,\n transactions: Array.from(txMap.values()),\n })\n }\n }\n\n return result\n }\n\n /**\n * Create a resolved version of transaction data with all addresses populated\n */\n createResolvedTransactionData(\n transactionData: DecoderResult,\n addresses: ReadonlyArray<DataKey>\n ): DecoderResult {\n // Clone the transaction data to avoid modifying the original\n const resolved = structuredClone(transactionData)\n\n // Create a map of address data for quick lookup\n const addressMap = new Map<string, EnhancedInfo>()\n\n for (const key of addresses) {\n const addressData = this.getData(key)\n if (addressData) {\n addressMap.set(key.toLowerCase(), addressData)\n }\n }\n\n // Use the path-based approach to replace addresses\n this.replaceAddressesWithPaths(resolved, addressMap)\n\n // Deep freeze the result\n return deepFreeze(resolved)\n }\n\n /**\n * Replace addresses using path information (similar to collectAddressesWithPaths)\n */\n private replaceAddressesWithPaths(\n data: unknown,\n addressMap: Map<string, EnhancedInfo>\n ): void {\n function traverse(\n obj: unknown,\n path: Array<string | number> = [],\n parent?: Record<string, unknown> | unknown[]\n ): void {\n // Handle string case first\n if (typeof obj === 'string' && obj.startsWith('0x')) {\n // Use regex to detect zero-padded addresses\n const isPaddedAddress = /^0x0*([a-fA-F0-9]{40})$/.test(obj)\n\n if (isPaddedAddress || (isHex(obj) && size(obj as Hex) === 20)) {\n // Extract the actual address (remove padding if needed)\n const address = isPaddedAddress\n ? (obj.replace(/^0x0*([a-fA-F0-9]{40})$/, '0x$1') as Address)\n : obj\n\n // Skip if too many zeros (likely not an address)\n if (\n address\n .slice(2)\n .split('')\n .filter((c: string) => c === '0').length > 10\n ) {\n return\n }\n\n // Check for tokenId in parent\n const currentKey = path[path.length - 1]\n const tokenId =\n parent &&\n !Array.isArray(parent) &&\n 'tokenId' in parent &&\n parent.tokenId\n ? (parent.tokenId as Hex)\n : undefined\n\n // Look up the address data\n let addressData: EnhancedInfo | undefined\n if (tokenId) {\n const compositeKey = `${address.toLowerCase()}_${tokenId.toLowerCase()}`\n addressData = addressMap.get(compositeKey)\n } else {\n addressData = addressMap.get(address.toLowerCase())\n }\n\n // Replace the address with the data if found\n if (addressData && parent) {\n if (Array.isArray(parent) && typeof currentKey === 'number') {\n parent[currentKey] = addressData\n } else if (\n !Array.isArray(parent) &&\n typeof currentKey === 'string'\n ) {\n parent[currentKey] = addressData\n }\n }\n }\n return\n }\n\n if (!obj || typeof obj !== 'object') return\n\n if (Array.isArray(obj)) {\n for (let index = 0; index < obj.length; index++) {\n traverse(obj[index], path.concat([index]), obj)\n }\n } else {\n const record = obj as Record<string, unknown>\n for (const [key, value] of Object.entries(record)) {\n traverse(value, path.concat([key]), record)\n }\n }\n }\n\n traverse(data)\n }\n\n /**\n * Update resolved transaction data for all transactions where addresses are loaded\n */\n private updateResolvedTransactionData(): void {\n // Go through all transactions\n for (const [_hash, txMap] of this.transactionSignals) {\n for (const [_decoderIndex, signal] of txMap) {\n const currentState = signal.value\n\n // Skip if already resolved or if no addresses\n if (\n currentState.addressesResolved ||\n currentState.addresses.length === 0\n ) {\n continue\n }\n\n // Check if all addresses are loaded\n let allAddressesLoaded = true\n for (const addressKey of currentState.addresses) {\n const addressState = this.getState(addressKey)\n if (addressState.loading || !addressState.data) {\n allAddressesLoaded = false\n break\n }\n }\n\n // If all addresses are loaded, create resolved data\n if (allAddressesLoaded) {\n const resolvedData = this.createResolvedTransactionData(\n currentState.data as DecoderResult,\n currentState.addresses\n )\n\n // Update the transaction state\n signal.value = {\n ...currentState,\n resolvedData: resolvedData as DeepReadonly<DecoderResult>,\n addressesResolved: true,\n lastUpdated: Date.now(),\n }\n }\n }\n }\n }\n\n /**\n * Get data by key - convenience method that handles both 20 and 32 byte addresses\n */\n getData(key: DataKey): DeepReadonly<EnhancedInfo> | undefined {\n return this.getState(key).data\n }\n\n /**\n * Check if a key is loading\n */\n isLoading(key: DataKey): boolean {\n return this.getState(key).loading\n }\n\n /**\n * Get error for a key\n */\n getError(key: DataKey): string | undefined {\n return this.getState(key).error\n }\n}\n\n/**\n * Create a read-only consumer proxy that only exposes safe read methods\n */\nexport function createConsumerProxy(model: DataModel): IDataModelConsumer {\n const consumerMethods = [\n // Transaction read methods\n 'getTransaction',\n 'getTransactionByKey',\n 'getTransactionsByIndex',\n 'getTransactionHashByIndex',\n 'getTransactionCount',\n 'getDecodedCount',\n 'getDecodedTransactions',\n 'getTransactionsInOrder',\n // Address read methods\n 'getAddress',\n 'getSignal',\n 'subscribe',\n 'getState',\n 'hasData',\n 'getData',\n 'isLoading',\n 'getError',\n // Collection read methods\n 'getAllKeys',\n 'getAllData',\n 'getAllTransactions',\n ]\n\n const proxy = new Proxy(model, {\n get(target, prop, receiver) {\n if (typeof prop === 'string' && consumerMethods.includes(prop)) {\n const value = Reflect.get(target, prop, receiver)\n if (typeof value === 'function') {\n return value.bind(target)\n }\n return value\n }\n // Block access to all other properties and methods\n return undefined\n },\n set() {\n return false // Prevent modifications\n },\n deleteProperty() {\n return false\n },\n defineProperty() {\n return false\n },\n setPrototypeOf() {\n return false\n },\n }) as IDataModelConsumer\n\n return proxy\n}\n\n/**\n * Create a secure DataModel instance\n * Freezes the prototype to prevent prototype pollution attacks\n */\nexport function createDataModel(options?: DataModelOptions): IDataModel {\n const model = new DataModel(options)\n\n // Freeze the prototype to prevent modification\n Object.freeze(DataModel.prototype)\n\n // Freeze the constructor\n Object.freeze(DataModel)\n\n return model\n}\n","import type { IDataModel, IDataModelConsumer } from '../types'\nimport { createConsumerProxy, DataModel } from './dataModel'\n\n// Create the singleton instance\nconst dataModelInstance = new DataModel()\n\n// Freeze the prototype and constructor to prevent prototype pollution\nObject.freeze(DataModel.prototype)\nObject.freeze(DataModel)\n\n// Export the full model for data providers to import\n// Note: We don't freeze dataModel as data providers need to modify it\nexport const dataModel: IDataModel = dataModelInstance\n\n// Create consumer-only proxy for public API (frozen)\nexport const consumerModel: IDataModelConsumer =\n createConsumerProxy(dataModelInstance)\n\n// Export a function to optionally create global instance\n// This allows consumers to control when/if the global is created\nexport function createGlobalInstance(): void {\n if (typeof window !== 'undefined') {\n // Create consumer-only proxy for window\n const consumerProxy = createConsumerProxy(dataModelInstance)\n\n Object.defineProperty(window, 'TransactionDecoder', {\n value: consumerProxy,\n writable: false,\n configurable: false,\n enumerable: true,\n })\n }\n}\n","import { type Signal, signal } from '@preact/signals-core'\nimport type { Hex, Transaction } from 'viem'\nimport { collectDataKeys } from '../core/addressCollector'\nimport { deepFreeze } from '../core/dataModel'\nimport { pluginRegistry } from '../decoder/registry'\nimport { decodeTransaction as decodeTransactionCore } from '../decoder/transaction'\nimport {\n AsyncOperations,\n type DecoderOptions,\n type DecoderResult,\n ErrorType,\n} from '../decoder/types'\nimport { isAsyncOperationEnabled } from '../decoder/utils'\nimport { ERROR_CODES } from '../shared/constants'\nimport type { DataKey, TransactionState } from '../types'\n\n/**\n * Address resolver interface for batch resolution\n */\nexport interface AddressResolver {\n resolveAddresses(addresses: DataKey[]): Promise<void>\n}\n\n/**\n * Result from decoding a transaction\n */\nexport interface TransactionDecoderResult {\n // Immediate sync result\n immediate: DecoderResult\n\n // Signal that updates as async decoding progresses\n signal: Signal<TransactionState>\n}\n\n/**\n * Decode a transaction with progressive enhancement\n * @param transaction - Raw transaction data or array of transactions\n * @param options - Decoder options\n * @returns Immediate result and reactive signal (or array of them)\n */\nexport async function decodeTransaction<\n T extends DecoderResult | DecoderResult[],\n>(\n transaction: T,\n options: DecoderOptions & { addressResolver?: AddressResolver }\n): Promise<\n T extends Transaction[]\n ? TransactionDecoderResult[]\n : TransactionDecoderResult\n> {\n const isBatch = Array.isArray(transaction)\n const transactions: DecoderResult[] = isBatch\n ? (transaction as unknown as DecoderResult[])\n : [transaction as DecoderResult]\n\n const results = await decodeTransactionBatch(transactions, options)\n\n // Return single result if single input\n if (isBatch) {\n return results as T extends Transaction[]\n ? TransactionDecoderResult[]\n : TransactionDecoderResult\n }\n return results[0] as T extends Transaction[]\n ? TransactionDecoderResult[]\n : TransactionDecoderResult\n}\n\n/**\n * Internal batch decoder with three-phase approach\n */\nasync function decodeTransactionBatch(\n transactions: DecoderResult[],\n options: DecoderOptions & { addressResolver?: AddressResolver }\n): Promise<TransactionDecoderResult[]> {\n // Extract names of plugins provided in options (these will override registered ones)\n const overridePluginNames =\n options.plugins\n ?.map((p) => p.name)\n .filter((name): name is string => typeof name === 'string') || []\n\n const overrideSchemaNames =\n options.schemaPlugins\n ?.map((p) => p.name)\n .filter((name): name is string => typeof name === 'string') || []\n\n // Get registered plugins, excluding those being overridden\n const registeredPlugins = await pluginRegistry.getAll({\n excludeNames: overridePluginNames,\n })\n const registeredSchemaPlugins =\n pluginRegistry.getAllSchema(overrideSchemaNames)\n\n // Merge: provided plugins override registered ones\n const allPlugins = [...registeredPlugins, ...(options.plugins || [])]\n const allSchemaPlugins = [\n ...registeredSchemaPlugins,\n ...(options.schemaPlugins || []),\n ]\n\n // Phase 1: Sync decode\n const syncOptions: DecoderOptions = {\n ...options,\n plugins: allPlugins.filter(({ usesAsync }) => !usesAsync),\n schemaPlugins: allSchemaPlugins,\n async: false,\n }\n\n const results = await Promise.all(\n transactions.map(async (tx) => {\n const initialResult = await decodeTransactionCore(tx, syncOptions)\n const initialData = deepFreeze(initialResult || createErrorResult(tx))\n\n // Create signal with frozen data\n const txSignal = signal<TransactionState>({\n loading: false,\n data: initialData as DecoderResult,\n decodingStatus: initialResult ? 'decoded' : 'failed',\n addresses: collectDataKeys(tx),\n addressesResolved: false,\n lastUpdated: Date.now(),\n })\n\n return {\n transaction: tx,\n immediate: initialData,\n signal: txSignal,\n }\n })\n )\n\n // Check if we have any async plugins for phase 2\n // For now, assume we have async plugins if async operations are enabled\n // since plugins themselves no longer have the async property\n const hasAsyncPlugins = true\n const pluginsEnabled = isAsyncOperationEnabled(\n options.async,\n AsyncOperations.ENABLE_PLUGINS\n )\n\n if (hasAsyncPlugins && pluginsEnabled) {\n // Phase 2: ABI retrieval (async plugins)\n const asyncOptions: DecoderOptions = {\n ...options,\n plugins: allPlugins,\n schemaPlugins: allSchemaPlugins,\n async: true,\n }\n\n // Run async decoding for all transactions\n for (const { transaction, signal: txSignal } of results) {\n decodeTransactionCore(transaction, asyncOptions)\n .then((enhanced) => {\n if (enhanced) {\n txSignal.value = {\n ...txSignal.value,\n data: deepFreeze(enhanced) as DecoderResult,\n decodingStatus: 'enhanced',\n addresses: collectDataKeys(enhanced),\n lastUpdated: Date.now(),\n }\n }\n })\n .catch((error) => {\n console.error('Async decode error:', error)\n txSignal.value = {\n ...txSignal.value,\n decodingStatus: 'failed',\n error: error instanceof Error ? error.message : 'Unknown error',\n loading: false,\n }\n })\n }\n }\n\n // Phase 3: Address resolution (if resolver provided and enabled)\n const addressResolveEnabled = isAsyncOperationEnabled(\n options.async,\n AsyncOperations.ENABLE_ADDRESS_RESOLVE\n )\n\n if (options.addressResolver && addressResolveEnabled) {\n // Collect all unique addresses from all transactions\n const allAddresses = new Set<DataKey>()\n for (const { signal: txSignal } of results) {\n for (const addr of txSignal.value.addresses) {\n allAddresses.add(addr)\n }\n }\n\n // Batch resolve addresses\n if (allAddresses.size > 0) {\n options.addressResolver\n .resolveAddresses(Array.from(allAddresses))\n .then(() => {\n // Update all signals to indicate addresses are resolved\n for (const { signal: txSignal } of results) {\n if (txSignal.value.decodingStatus !== 'failed') {\n txSignal.value = {\n ...txSignal.value,\n addressesResolved: true,\n decodingStatus: 'complete',\n lastUpdated: Date.now(),\n }\n }\n }\n })\n .catch((error) => {\n console.error('Address resolution error:', error)\n // Don't fail the transaction, just log the error\n })\n }\n } else if (!hasAsyncPlugins || (!pluginsEnabled && !addressResolveEnabled)) {\n // No async operations enabled, mark as complete\n for (const { signal: txSignal } of results) {\n if (txSignal.value.decodingStatus !== 'failed') {\n txSignal.value = {\n ...txSignal.value,\n decodingStatus: 'complete',\n }\n }\n }\n }\n\n return results.map((r) => ({\n immediate: r.immediate,\n signal: r.signal,\n }))\n}\n\nfunction createErrorResult(transaction: DecoderResult): DecoderResult {\n return {\n ...transaction,\n resultType: 'error' as const,\n isDecoded: false,\n errorType: ErrorType.ERROR,\n sig: transaction.input?.slice(0, 10) as Hex,\n error: {\n code: ERROR_CODES.DECODING_FAILED,\n message: 'Failed to decode transaction',\n details: new Error('Decoder returned undefined'),\n },\n }\n}\n\n/**\n * Decode a transaction and wait for complete result\n * Convenience wrapper for when you need a promise\n */\nexport async function decodeTransactionAsync<\n T extends DecoderResult | DecoderResult[],\n>(\n transaction: T,\n options: DecoderOptions & { addressResolver?: AddressResolver }\n): Promise<T extends Transaction[] ? DecoderResult[] : DecoderResult> {\n const isBatch = Array.isArray(transaction)\n const result = await decodeTransaction(transaction, options)\n const results = isBatch\n ? (result as TransactionDecoderResult[])\n : [result as TransactionDecoderResult]\n\n // Wait for all decodings to complete\n const finalResults = await Promise.all(\n results.map(\n ({ signal }) =>\n new Promise<DecoderResult>((resolve) => {\n const checkComplete = () => {\n const state = signal.value\n if (\n state.decodingStatus === 'complete' ||\n state.decodingStatus === 'failed'\n ) {\n resolve(state.data as DecoderResult)\n } else {\n // Check again on next tick\n setTimeout(checkComplete, 10)\n }\n }\n checkComplete()\n })\n )\n )\n\n if (isBatch) {\n return finalResults as T extends Transaction[]\n ? DecoderResult[]\n : DecoderResult\n }\n return finalResults[0] as T extends Transaction[]\n ? DecoderResult[]\n : DecoderResult\n}\n","/**\n * Shared constants\n */\n\nexport const DECODER_VERSION = '0.1.0'\n\nexport const DEFAULT_CONFIG = {\n endpoint: 'https://api.lukso.network/decoder',\n batchSize: 100,\n retryAttempts: 3,\n timeout: 30000,\n} as const\n\nexport const ERROR_CODES = {\n INVALID_TRANSACTION: 'INVALID_TRANSACTION',\n DECODING_FAILED: 'DECODING_FAILED',\n NETWORK_ERROR: 'NETWORK_ERROR',\n RATE_LIMIT: 'RATE_LIMIT',\n UNAUTHORIZED: 'UNAUTHORIZED',\n NOT_FOUND: 'NOT_FOUND',\n} as const\n"],"mappings":"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","names":["signal","signal","decodeTransaction","signal"]}