@lukso/transaction-decoder 1.3.6-dev.ea75859 → 1.3.7-dev.2df3eae
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser.cjs +214 -24
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.cts +2 -2
- package/dist/browser.d.ts +2 -2
- package/dist/browser.js +4 -4
- package/dist/cdn/transaction-decoder.global.js +75 -75
- package/dist/cdn/transaction-decoder.global.js.map +1 -1
- package/dist/{chunk-NDBDNXBI.js → chunk-C3O7HMFS.js} +2 -2
- package/dist/{chunk-FKBKAWB3.js → chunk-JP3VO7OF.js} +2 -2
- package/dist/{chunk-SSY7TTU2.js → chunk-LZFM5SNN.js} +4 -4
- package/dist/{chunk-T4H2HHIB.js → chunk-XE5YIF5G.js} +209 -19
- package/dist/chunk-XE5YIF5G.js.map +1 -0
- package/dist/data.cjs +208 -18
- package/dist/data.cjs.map +1 -1
- package/dist/data.d.cts +3 -3
- package/dist/data.d.ts +3 -3
- package/dist/data.js +2 -2
- package/dist/{index-BzXh7poJ.d.ts → index-BWD9DaG6.d.cts} +6 -1
- package/dist/{index-BzXh7poJ.d.cts → index-BWD9DaG6.d.ts} +6 -1
- package/dist/index.cjs +214 -24
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +4 -4
- package/dist/server.cjs +1499 -1258
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +17 -2
- package/dist/server.d.ts +17 -2
- package/dist/server.js +56 -2
- package/dist/server.js.map +1 -1
- package/dist/{utils-De_c6fUK.d.ts → utils-4Qdavg8r.d.ts} +2 -2
- package/dist/{utils-BEpSreRR.d.cts → utils-OR-XzeYG.d.cts} +2 -2
- package/package.json +8 -8
- package/src/decoder/lsp7Mint.test.ts +18 -11
- package/src/decoder/plugins/enhanceLSP0ERC725Account.ts +39 -2
- package/src/decoder/plugins/universalReceiverTypeIds.ts +277 -0
- package/src/decoder/types.ts +2 -0
- package/src/server/decodeEventLogs.ts +71 -0
- package/src/server/index.ts +10 -0
- package/src/server/types.ts +14 -1
- package/src/server.ts +1 -0
- package/src/types/index.ts +5 -1
- package/dist/chunk-T4H2HHIB.js.map +0 -1
- /package/dist/{chunk-NDBDNXBI.js.map → chunk-C3O7HMFS.js.map} +0 -0
- /package/dist/{chunk-FKBKAWB3.js.map → chunk-JP3VO7OF.js.map} +0 -0
- /package/dist/{chunk-SSY7TTU2.js.map → chunk-LZFM5SNN.js.map} +0 -0
package/dist/server.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Chain, Abi } from 'viem';
|
|
2
|
-
import {
|
|
2
|
+
import { c as DecoderResult, b as DataKey, E as EnhancedInfo, a as DecodeEventResult, e as Info } from './index-BWD9DaG6.cjs';
|
|
3
3
|
import '@preact/signals-core';
|
|
4
4
|
import '@erc725/erc725.js';
|
|
5
5
|
|
|
@@ -137,6 +137,10 @@ interface ServerDecoder {
|
|
|
137
137
|
* Uses cache when available
|
|
138
138
|
*/
|
|
139
139
|
resolveAddresses: (addresses: DataKey[], timeoutMs?: number) => Promise<Map<DataKey, EnhancedInfo>>;
|
|
140
|
+
/**
|
|
141
|
+
* Decode an array of raw log events using registered decoder plugins
|
|
142
|
+
*/
|
|
143
|
+
decodeEventLogs: (logs: DecodeEventResult[], options?: Partial<ServerDecoderOptions>) => Promise<DecodeEventResult[]>;
|
|
140
144
|
}
|
|
141
145
|
|
|
142
146
|
/**
|
|
@@ -198,6 +202,17 @@ declare class ServerAddressResolver {
|
|
|
198
202
|
warmCache(addresses: DataKey[]): Promise<void>;
|
|
199
203
|
}
|
|
200
204
|
|
|
205
|
+
/**
|
|
206
|
+
* Decode an array of raw log events using the registered decoder plugins.
|
|
207
|
+
*
|
|
208
|
+
* Uses the same plugin iteration pattern as transaction.ts:
|
|
209
|
+
* try each plugin's `decodeEvent`, first match wins, raw log kept as fallback.
|
|
210
|
+
*
|
|
211
|
+
* For DataChanged events, also decodes the ERC725Y key-value pair using
|
|
212
|
+
* the schema plugin system (same as setData transaction decoding).
|
|
213
|
+
*/
|
|
214
|
+
declare function decodeEventLogs(logs: DecodeEventResult[], options: ServerDecoderOptions, _caches: ServerDecoderCaches): Promise<DecodeEventResult[]>;
|
|
215
|
+
|
|
201
216
|
/**
|
|
202
217
|
* Decode a single transaction with time-bounded enhancement
|
|
203
218
|
*/
|
|
@@ -213,4 +228,4 @@ declare function decodeTransactionsBatch(transactions: DecoderResult[], options:
|
|
|
213
228
|
*/
|
|
214
229
|
declare function createServerDecoder(config: ServerDecoderConfig): ServerDecoder;
|
|
215
230
|
|
|
216
|
-
export { type CacheStats, ServerAddressResolver, type ServerDecoder, ServerDecoderCaches, type ServerDecoderConfig, type ServerDecoderOptions, createServerDecoder, decodeTransactionSync, decodeTransactionsBatch };
|
|
231
|
+
export { type CacheStats, ServerAddressResolver, type ServerDecoder, ServerDecoderCaches, type ServerDecoderConfig, type ServerDecoderOptions, createServerDecoder, decodeEventLogs, decodeTransactionSync, decodeTransactionsBatch };
|
package/dist/server.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Chain, Abi } from 'viem';
|
|
2
|
-
import {
|
|
2
|
+
import { c as DecoderResult, b as DataKey, E as EnhancedInfo, a as DecodeEventResult, e as Info } from './index-BWD9DaG6.js';
|
|
3
3
|
import '@preact/signals-core';
|
|
4
4
|
import '@erc725/erc725.js';
|
|
5
5
|
|
|
@@ -137,6 +137,10 @@ interface ServerDecoder {
|
|
|
137
137
|
* Uses cache when available
|
|
138
138
|
*/
|
|
139
139
|
resolveAddresses: (addresses: DataKey[], timeoutMs?: number) => Promise<Map<DataKey, EnhancedInfo>>;
|
|
140
|
+
/**
|
|
141
|
+
* Decode an array of raw log events using registered decoder plugins
|
|
142
|
+
*/
|
|
143
|
+
decodeEventLogs: (logs: DecodeEventResult[], options?: Partial<ServerDecoderOptions>) => Promise<DecodeEventResult[]>;
|
|
140
144
|
}
|
|
141
145
|
|
|
142
146
|
/**
|
|
@@ -198,6 +202,17 @@ declare class ServerAddressResolver {
|
|
|
198
202
|
warmCache(addresses: DataKey[]): Promise<void>;
|
|
199
203
|
}
|
|
200
204
|
|
|
205
|
+
/**
|
|
206
|
+
* Decode an array of raw log events using the registered decoder plugins.
|
|
207
|
+
*
|
|
208
|
+
* Uses the same plugin iteration pattern as transaction.ts:
|
|
209
|
+
* try each plugin's `decodeEvent`, first match wins, raw log kept as fallback.
|
|
210
|
+
*
|
|
211
|
+
* For DataChanged events, also decodes the ERC725Y key-value pair using
|
|
212
|
+
* the schema plugin system (same as setData transaction decoding).
|
|
213
|
+
*/
|
|
214
|
+
declare function decodeEventLogs(logs: DecodeEventResult[], options: ServerDecoderOptions, _caches: ServerDecoderCaches): Promise<DecodeEventResult[]>;
|
|
215
|
+
|
|
201
216
|
/**
|
|
202
217
|
* Decode a single transaction with time-bounded enhancement
|
|
203
218
|
*/
|
|
@@ -213,4 +228,4 @@ declare function decodeTransactionsBatch(transactions: DecoderResult[], options:
|
|
|
213
228
|
*/
|
|
214
229
|
declare function createServerDecoder(config: ServerDecoderConfig): ServerDecoder;
|
|
215
230
|
|
|
216
|
-
export { type CacheStats, ServerAddressResolver, type ServerDecoder, ServerDecoderCaches, type ServerDecoderConfig, type ServerDecoderOptions, createServerDecoder, decodeTransactionSync, decodeTransactionsBatch };
|
|
231
|
+
export { type CacheStats, ServerAddressResolver, type ServerDecoder, ServerDecoderCaches, type ServerDecoderConfig, type ServerDecoderOptions, createServerDecoder, decodeEventLogs, decodeTransactionSync, decodeTransactionsBatch };
|
package/dist/server.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
fetchMultipleAddresses
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-JP3VO7OF.js";
|
|
4
4
|
import {
|
|
5
5
|
__name,
|
|
6
6
|
collectDataKeys,
|
|
7
7
|
createDebug,
|
|
8
|
+
decodeKeyValueRaw,
|
|
8
9
|
decodeTransaction,
|
|
9
10
|
needsEnhancement,
|
|
10
11
|
pluginRegistry
|
|
11
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-XE5YIF5G.js";
|
|
12
13
|
|
|
13
14
|
// src/server/addressResolver.ts
|
|
14
15
|
var ServerAddressResolver = class {
|
|
@@ -233,6 +234,50 @@ var ServerDecoderCaches = class {
|
|
|
233
234
|
}
|
|
234
235
|
};
|
|
235
236
|
|
|
237
|
+
// src/server/decodeEventLogs.ts
|
|
238
|
+
async function decodeEventLogs(logs, options, _caches) {
|
|
239
|
+
const { chain } = options;
|
|
240
|
+
const plugins = await pluginRegistry.getAll({ syncOnly: true });
|
|
241
|
+
const schemaPlugins = pluginRegistry.getAllSchema();
|
|
242
|
+
const decoderOptions = {
|
|
243
|
+
chain,
|
|
244
|
+
plugins,
|
|
245
|
+
schemaPlugins,
|
|
246
|
+
wrappers: [],
|
|
247
|
+
async: false
|
|
248
|
+
};
|
|
249
|
+
const results = [];
|
|
250
|
+
for (const log of logs) {
|
|
251
|
+
let decoded;
|
|
252
|
+
for (const plugin of plugins) {
|
|
253
|
+
decoded = await plugin.decodeEvent(log, decoderOptions);
|
|
254
|
+
if (decoded) break;
|
|
255
|
+
}
|
|
256
|
+
const result = decoded ?? log;
|
|
257
|
+
if (result?.eventName === "DataChanged" && result.args) {
|
|
258
|
+
try {
|
|
259
|
+
const dataKey = result.args.find((a) => a.name === "dataKey")?.value;
|
|
260
|
+
const dataValue = result.args.find((a) => a.name === "dataValue")?.value;
|
|
261
|
+
if (dataKey) {
|
|
262
|
+
const info = await decodeKeyValueRaw(
|
|
263
|
+
dataKey,
|
|
264
|
+
dataValue ?? "0x",
|
|
265
|
+
decoderOptions
|
|
266
|
+
);
|
|
267
|
+
if (info) {
|
|
268
|
+
;
|
|
269
|
+
result.info = info;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
} catch {
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
results.push(result);
|
|
276
|
+
}
|
|
277
|
+
return results;
|
|
278
|
+
}
|
|
279
|
+
__name(decodeEventLogs, "decodeEventLogs");
|
|
280
|
+
|
|
236
281
|
// src/server/decodeTransactionSync.ts
|
|
237
282
|
async function decodeTransactionSync(transaction, options, caches) {
|
|
238
283
|
const startTime = Date.now();
|
|
@@ -625,6 +670,14 @@ function createServerDecoder(config) {
|
|
|
625
670
|
},
|
|
626
671
|
async resolveAddresses(addresses, timeoutMs = 3e3) {
|
|
627
672
|
return addressResolver.resolveAddressesWithTimeout(addresses, timeoutMs);
|
|
673
|
+
},
|
|
674
|
+
async decodeEventLogs(logs, options) {
|
|
675
|
+
const opts = {
|
|
676
|
+
chain: config.defaultChain,
|
|
677
|
+
timeoutMs: config.defaultTimeout,
|
|
678
|
+
...options
|
|
679
|
+
};
|
|
680
|
+
return decodeEventLogs(logs, opts, caches);
|
|
628
681
|
}
|
|
629
682
|
};
|
|
630
683
|
}
|
|
@@ -633,6 +686,7 @@ export {
|
|
|
633
686
|
ServerAddressResolver,
|
|
634
687
|
ServerDecoderCaches,
|
|
635
688
|
createServerDecoder,
|
|
689
|
+
decodeEventLogs,
|
|
636
690
|
decodeTransactionSync,
|
|
637
691
|
decodeTransactionsBatch
|
|
638
692
|
};
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server/addressResolver.ts","../src/server/caches.ts","../src/server/decodeTransactionSync.ts","../src/server/decodeTransactionsBatch.ts","../src/server/finishDecoding.ts","../src/server/index.ts"],"sourcesContent":["import type { Chain } from 'viem'\nimport { fetchMultipleAddresses } from '../shared/addressResolver'\nimport type { AddressIdentityCache } from '../shared/cache'\nimport type { DataKey, EnhancedInfo } from '../types'\nimport type { ServerDecoderCaches } from './caches'\n\n/**\n * Server-side address resolver with caching\n */\nexport class ServerAddressResolver {\n private cacheAdapter: AddressIdentityCache\n\n constructor(\n private graphqlEndpoint: string,\n _chain: Chain,\n private caches: ServerDecoderCaches\n ) {\n // Create adapter to use ServerDecoderCaches as AddressIdentityCache\n this.cacheAdapter = {\n get: (key: DataKey) => this.caches.getAddress(key),\n set: (key: DataKey, value: EnhancedInfo) =>\n this.caches.setAddress(key, value),\n has: (key: DataKey) => this.caches.hasAddress(key),\n getMany: (keys: DataKey[]) => this.caches.getAddresses(keys),\n }\n }\n\n /**\n * Resolve addresses, using cache when possible\n */\n async resolveAddresses(\n addresses: readonly DataKey[]\n ): Promise<Map<DataKey, EnhancedInfo>> {\n // Use the shared implementation with cache adapter\n return fetchMultipleAddresses(\n addresses,\n this.graphqlEndpoint,\n this.cacheAdapter\n )\n }\n\n /**\n * Resolve addresses with timeout\n */\n async resolveAddressesWithTimeout(\n addresses: DataKey[],\n timeoutMs: number\n ): Promise<Map<DataKey, EnhancedInfo>> {\n return Promise.race([\n this.resolveAddresses(addresses),\n new Promise<Map<DataKey, EnhancedInfo>>((resolve) => {\n setTimeout(() => {\n // On timeout, return whatever we have cached\n const results = this.caches.getAddresses(addresses)\n resolve(results)\n }, timeoutMs)\n }),\n ])\n }\n\n /**\n * Warm the cache with specific addresses\n */\n async warmCache(addresses: DataKey[]): Promise<void> {\n // Simply call resolveAddresses which will cache any uncached addresses\n await this.resolveAddresses(addresses)\n }\n}\n","import { LRUCache } from 'lru-cache'\nimport type { Abi } from 'viem'\nimport type { DecoderResult, Info } from '../decoder/types'\nimport type { DataKey, EnhancedInfo } from '../types'\nimport type { CacheStats } from './types'\n\n/**\n * Multi-level caching system for server-side decoder\n */\nexport class ServerDecoderCaches {\n // Level 1: Decoded transaction cache (keyed by transaction hash)\n private transactionCache: LRUCache<string, DecoderResult>\n private transactionStats = { hits: 0, misses: 0 }\n\n // Level 2: Address metadata cache (keyed by address or address:tokenId)\n private addressCache: LRUCache<string, EnhancedInfo>\n private addressStats = { hits: 0, misses: 0 }\n\n // Level 3: Contract ABI cache (keyed by address)\n private abiCache: LRUCache<string, Abi>\n private abiStats = { hits: 0, misses: 0 }\n\n // Level 4: Schema decode cache (keyed by key:value)\n private schemaCache: LRUCache<string, Info>\n private schemaStats = { hits: 0, misses: 0 }\n\n constructor(\n options: {\n transactionCacheSize?: number\n addressCacheSize?: number\n abiCacheSize?: number\n schemaCacheSize?: number\n } = {}\n ) {\n // Transaction cache - store complete decoded results\n this.transactionCache = new LRUCache<string, DecoderResult>({\n max: options.transactionCacheSize || 10000,\n ttl: 1000 * 60 * 60, // 1 hour TTL\n updateAgeOnGet: true,\n updateAgeOnHas: true,\n })\n\n // Address cache - store profile/asset metadata\n this.addressCache = new LRUCache<string, EnhancedInfo>({\n max: options.addressCacheSize || 50000,\n ttl: 1000 * 60 * 60 * 24, // 24 hour TTL\n updateAgeOnGet: true,\n updateAgeOnHas: true,\n })\n\n // ABI cache - store contract ABIs\n this.abiCache = new LRUCache<string, Abi>({\n max: options.abiCacheSize || 5000,\n ttl: 1000 * 60 * 60 * 24 * 7, // 7 day TTL (ABIs rarely change)\n updateAgeOnGet: true,\n updateAgeOnHas: true,\n })\n\n // Schema cache - store decoded schema values\n this.schemaCache = new LRUCache<string, Info>({\n max: options.schemaCacheSize || 10000,\n ttl: 1000 * 60 * 60, // 1 hour TTL\n updateAgeOnGet: true,\n updateAgeOnHas: true,\n })\n }\n\n /**\n * Get cache key for a data key (address or address:tokenId)\n */\n private getDataKeyCacheKey(key: DataKey): string {\n return key.toLowerCase()\n }\n\n // Transaction cache methods\n getTransaction(hash: string): DecoderResult | undefined {\n const result = this.transactionCache.get(hash.toLowerCase())\n if (result) {\n this.transactionStats.hits++\n return { ...result, cached: true }\n }\n this.transactionStats.misses++\n return undefined\n }\n\n setTransaction(hash: string, result: DecoderResult): void {\n this.transactionCache.set(hash.toLowerCase(), result)\n }\n\n // Address cache methods\n getAddress(key: DataKey): EnhancedInfo | undefined {\n const cacheKey = this.getDataKeyCacheKey(key)\n const result = this.addressCache.get(cacheKey)\n if (result) {\n this.addressStats.hits++\n return result\n }\n this.addressStats.misses++\n return undefined\n }\n\n setAddress(key: DataKey, data: EnhancedInfo): void {\n const cacheKey = this.getDataKeyCacheKey(key)\n this.addressCache.set(cacheKey, data)\n }\n\n hasAddress(key: DataKey): boolean {\n return this.addressCache.has(this.getDataKeyCacheKey(key))\n }\n\n getAddresses(keys: DataKey[]): Map<DataKey, EnhancedInfo> {\n const results = new Map<DataKey, EnhancedInfo>()\n for (const key of keys) {\n const data = this.getAddress(key)\n if (data) {\n results.set(key, data)\n }\n }\n return results\n }\n\n // ABI cache methods\n getAbi(address: string): Abi | undefined {\n const result = this.abiCache.get(address.toLowerCase())\n if (result) {\n this.abiStats.hits++\n return result\n }\n this.abiStats.misses++\n return undefined\n }\n\n setAbi(address: string, abi: Abi): void {\n this.abiCache.set(address.toLowerCase(), abi)\n }\n\n hasAbi(address: string): boolean {\n return this.abiCache.has(address.toLowerCase())\n }\n\n // Schema cache methods\n getSchema(key: string, value: string): Info | undefined {\n const cacheKey = `${key}:${value}`\n const result = this.schemaCache.get(cacheKey)\n if (result) {\n this.schemaStats.hits++\n return result\n }\n this.schemaStats.misses++\n return undefined\n }\n\n setSchema(key: string, value: string, info: Info): void {\n const cacheKey = `${key}:${value}`\n this.schemaCache.set(cacheKey, info)\n }\n\n // Cache management\n clear(): void {\n this.transactionCache.clear()\n this.addressCache.clear()\n this.abiCache.clear()\n this.schemaCache.clear()\n\n // Reset stats\n this.transactionStats = { hits: 0, misses: 0 }\n this.addressStats = { hits: 0, misses: 0 }\n this.abiStats = { hits: 0, misses: 0 }\n this.schemaStats = { hits: 0, misses: 0 }\n }\n\n getStats(): CacheStats {\n const calculateHitRate = (stats: { hits: number; misses: number }) => {\n const total = stats.hits + stats.misses\n return total > 0 ? stats.hits / total : 0\n }\n\n return {\n transactions: {\n size: this.transactionCache.size,\n maxSize: this.transactionCache.max,\n hits: this.transactionStats.hits,\n misses: this.transactionStats.misses,\n hitRate: calculateHitRate(this.transactionStats),\n },\n addresses: {\n size: this.addressCache.size,\n maxSize: this.addressCache.max,\n hits: this.addressStats.hits,\n misses: this.addressStats.misses,\n hitRate: calculateHitRate(this.addressStats),\n },\n abis: {\n size: this.abiCache.size,\n maxSize: this.abiCache.max,\n hits: this.abiStats.hits,\n misses: this.abiStats.misses,\n hitRate: calculateHitRate(this.abiStats),\n },\n schemas: {\n size: this.schemaCache.size,\n maxSize: this.schemaCache.max,\n hits: this.schemaStats.hits,\n misses: this.schemaStats.misses,\n hitRate: calculateHitRate(this.schemaStats),\n },\n }\n }\n}\n","import { collectDataKeys } from '../core/addressCollector'\nimport { pluginRegistry } from '../decoder/registry'\nimport { decodeTransaction as decodeTransactionCore } from '../decoder/transaction'\nimport type { DecoderResult } from '../decoder/types'\nimport { needsEnhancement } from '../decoder/utils'\nimport type { ServerDecoderCaches } from './caches'\nimport type { ServerDecoderOptions } from './types'\n\n/**\n * Decode a single transaction with time-bounded enhancement\n */\nexport async function decodeTransactionSync(\n transaction: DecoderResult,\n options: ServerDecoderOptions,\n caches: ServerDecoderCaches\n): Promise<DecoderResult> {\n const startTime = Date.now()\n const { timeoutMs = 800, enableEnhancement = true, chain } = options\n\n // Check transaction cache first\n if (transaction.hash) {\n const cached = caches.getTransaction(transaction.hash)\n if (cached) {\n return cached\n }\n }\n\n try {\n // Phase 1: Immediate decode (sync plugins only)\n const phase1Start = Date.now()\n const plugins = await pluginRegistry.getAll({ syncOnly: true })\n const schemaPlugins = pluginRegistry.getAllSchema()\n\n const immediateOptions = {\n chain,\n plugins,\n schemaPlugins,\n wrappers: [],\n async: false,\n }\n const immediateResult = await decodeTransactionCore(\n transaction,\n immediateOptions\n )\n\n if (!immediateResult) {\n return {\n ...createErrorResult(transaction),\n phase: 'immediate',\n cached: false,\n timeTaken: Date.now() - startTime,\n }\n }\n\n let currentResult: DecoderResult = immediateResult\n let phase: 'immediate' | 'enhanced' | 'complete' = 'immediate'\n\n // Transfer collected wrappers if any\n if (immediateOptions.wrappers.length > 0) {\n ;(currentResult as any).wrappers = immediateOptions.wrappers\n }\n\n // Collect addresses from the decoded result\n const addresses = collectDataKeys(currentResult)\n currentResult.addresses = addresses\n\n // Check if we have time for enhancement\n const phase1Time = Date.now() - phase1Start\n if (enableEnhancement && phase1Time < timeoutMs * 0.6) {\n // Check if enhancement is actually needed\n if (!needsEnhancement(currentResult)) {\n // Already fully decoded during immediate phase\n phase = 'enhanced'\n } else {\n // Phase 2: Enhancement with async plugins\n try {\n const allPlugins = await pluginRegistry.getAll()\n const enhancedOptions = {\n chain,\n plugins: allPlugins,\n schemaPlugins,\n wrappers: [],\n async: true,\n }\n const enhancedResult = await Promise.race([\n decodeTransactionCore(transaction, enhancedOptions),\n // Timeout for phase 2\n new Promise<null>((resolve) =>\n setTimeout(() => resolve(null), timeoutMs * 0.6 - phase1Time)\n ),\n ])\n\n if (enhancedResult) {\n currentResult = enhancedResult\n phase = 'enhanced'\n\n // Merge wrappers from both phases (immediate + enhanced)\n const allWrappers = [\n ...((immediateOptions.wrappers || []) as any[]),\n ...(enhancedOptions.wrappers || []),\n ].filter(\n (w, i, arr) =>\n // Deduplicate by checking if this is the first occurrence\n arr.findIndex(\n (x) => JSON.stringify(x) === JSON.stringify(w)\n ) === i\n )\n\n if (allWrappers.length > 0) {\n ;(currentResult as any).wrappers = allWrappers\n }\n\n // Re-collect addresses from enhanced result\n currentResult.addresses = collectDataKeys(currentResult)\n }\n } catch (error) {\n console.error('Enhancement failed:', error)\n }\n }\n }\n\n const result: DecoderResult = {\n ...currentResult,\n phase,\n cached: false,\n timeTaken: Date.now() - startTime,\n }\n\n // Cache the result if we have a hash\n if (transaction.hash) {\n caches.setTransaction(transaction.hash, result)\n }\n\n return result\n } catch (error) {\n console.error('Failed to decode transaction:', error)\n return {\n ...createErrorResult(transaction),\n phase: 'immediate',\n cached: false,\n timeTaken: Date.now() - startTime,\n }\n }\n}\n\nfunction createErrorResult(transaction: DecoderResult): DecoderResult {\n return {\n ...transaction,\n isDecoded: false,\n resultType: 'error',\n errorType: 'UNKNOWN',\n sig: '0x' as `0x${string}`,\n addresses: [],\n } as DecoderResult\n}\n","import { collectDataKeys } from '../core/addressCollector'\nimport { pluginRegistry } from '../decoder/registry'\nimport { decodeTransaction as decodeTransactionCore } from '../decoder/transaction'\nimport type { DecoderResult, ResultShared } from '../decoder/types'\nimport { needsEnhancement } from '../decoder/utils'\nimport type { ServerDecoderCaches } from './caches'\nimport type { BatchDecodeResult, ServerDecoderOptions } from './types'\n\n/**\n * Decode multiple transactions with batching and time budget\n */\nexport async function decodeTransactionsBatch(\n transactions: DecoderResult[],\n options: ServerDecoderOptions,\n caches: ServerDecoderCaches\n): Promise<BatchDecodeResult> {\n const startTime = Date.now()\n const { timeoutMs = 800, enableEnhancement = true, chain } = options\n\n // Step 1: Check cache for all transactions\n const results: (DecoderResult | null)[] = transactions.map((tx) => {\n if (tx.transactionHash) {\n const cached = caches.getTransaction(tx.transactionHash)\n if (cached) return cached\n }\n return null\n })\n\n // Find uncached transactions\n const uncachedIndexes: number[] = []\n const uncachedTransactions: DecoderResult[] = []\n results.forEach((result, index) => {\n if (!result) {\n uncachedIndexes.push(index)\n uncachedTransactions.push(transactions[index])\n }\n })\n\n // If all are cached, return early\n if (uncachedTransactions.length === 0) {\n return {\n results: results as DecoderResult[],\n }\n }\n\n try {\n // Get plugins once for all transactions\n const syncPlugins = await pluginRegistry.getAll({ syncOnly: true })\n const allPlugins = await pluginRegistry.getAll()\n const schemaPlugins = pluginRegistry.getAllSchema()\n\n // Phase 1: Immediate decode for all uncached transactions\n const phase1Start = Date.now()\n const immediateOptionsArray = uncachedTransactions.map(() => ({\n chain,\n plugins: syncPlugins,\n schemaPlugins,\n wrappers: [],\n async: false,\n }))\n\n const immediateResults: DecoderResult[] = (\n await Promise.all(\n uncachedTransactions.map(async (tx, i) => {\n return await decodeTransactionCore(tx, immediateOptionsArray[i])\n })\n )\n ).filter(Boolean) as DecoderResult[]\n\n // Create result objects and collect addresses\n const newResults: DecoderResult[] = immediateResults\n .map((result, i) => {\n const data = result || createErrorResult(uncachedTransactions[i])\n\n // Transfer wrappers from immediate phase options\n if (immediateOptionsArray[i].wrappers.length > 0) {\n ;(data as any).wrappers = immediateOptionsArray[i].wrappers\n }\n\n // Collect addresses from the decoded result\n data.addresses = collectDataKeys(data)\n ;(data as ResultShared).timeTaken = Date.now() - startTime\n return data\n })\n .filter(Boolean) as DecoderResult[]\n\n // Check if we have time for enhancement\n const phase1Time = Date.now() - phase1Start\n if (enableEnhancement && phase1Time < timeoutMs * 0.6) {\n // Phase 2: Enhancement with async plugins (batch all transactions)\n try {\n const enhancedOptionsArray = uncachedTransactions.map(() => ({\n chain,\n plugins: allPlugins,\n schemaPlugins,\n wrappers: [],\n async: true,\n }))\n\n const enhancePromises = uncachedTransactions.map((tx, i) => {\n // Only enhance if immediate decode succeeded\n if (!immediateResults[i]) return null\n\n // Check if enhancement is actually needed\n if (!needsEnhancement(immediateResults[i])) {\n // Already fully decoded during immediate phase\n return null\n }\n\n return decodeTransactionCore(tx, enhancedOptionsArray[i])\n })\n\n // Wait for all enhancements with remaining time budget\n const _remainingTime = timeoutMs * 0.6 - phase1Time\n const enhancedResults = await Promise.all(enhancePromises)\n\n // Update results with enhanced data\n enhancedResults.forEach((enhanced, i) => {\n if (enhanced) {\n // Merge wrappers from both phases (immediate + enhanced)\n const immediateWrappers = immediateOptionsArray[i].wrappers || []\n const enhancedWrappers = enhancedOptionsArray[i].wrappers || []\n const allWrappers = [\n ...immediateWrappers,\n ...enhancedWrappers,\n ].filter(\n (w, idx, arr) =>\n // Deduplicate by checking if this is the first occurrence\n arr.findIndex(\n (x) => JSON.stringify(x) === JSON.stringify(w)\n ) === idx\n )\n\n // Enhancement returned a new result\n newResults[i] = enhanced\n\n // Add merged wrappers if any\n if (allWrappers.length > 0) {\n ;(newResults[i] as any).wrappers = allWrappers\n }\n\n // Re-collect addresses from enhanced result\n newResults[i].addresses = collectDataKeys(enhanced)\n newResults[i].phase = 'enhanced'\n } else if (\n immediateResults[i] &&\n !needsEnhancement(immediateResults[i])\n ) {\n // Enhancement was skipped because already fully decoded\n newResults[i].phase = 'enhanced'\n }\n })\n } catch (error) {\n console.error('Batch enhancement failed:', error)\n }\n }\n\n // Update timings\n const totalTime = Date.now() - startTime\n newResults.forEach((result) => {\n result.timeTaken = totalTime\n })\n\n // Cache all new results\n newResults.forEach((result, i) => {\n const tx = uncachedTransactions[i]\n if (tx.hash) {\n caches.setTransaction(tx.hash, result)\n }\n })\n\n // Merge cached and new results\n uncachedIndexes.forEach((originalIndex, i) => {\n results[originalIndex] = newResults[i]\n })\n\n return {\n results: results as DecoderResult[],\n }\n } catch (error) {\n console.error('Batch decode failed:', error)\n // Return error results for uncached transactions\n uncachedIndexes.forEach((originalIndex) => {\n results[originalIndex] = {\n ...createErrorResult(transactions[originalIndex]),\n phase: 'immediate',\n cached: false,\n timeTaken: Date.now() - startTime,\n }\n })\n\n return {\n results: results as DecoderResult[],\n }\n }\n}\n\nfunction createErrorResult(transaction: DecoderResult): DecoderResult {\n return {\n ...transaction,\n isDecoded: false,\n resultType: 'error',\n errorType: 'UNKNOWN',\n sig: '0x' as `0x${string}`,\n addresses: [],\n } as DecoderResult\n}\n","import { pluginRegistry } from '../decoder/registry'\nimport { decodeTransaction as decodeTransactionCore } from '../decoder/transaction'\nimport type { DecoderResult } from '../decoder/types'\nimport { createDebug } from '../utils/debug'\nimport type { ServerDecoderCaches } from './caches'\nimport type { ServerDecoderOptions } from './types'\n\nconst _debug = createDebug('decoder:finishDecoding')\n\n/**\n * Finish decoding a transaction by running enhancement phase\n * This only does phase 2 (async plugins) - address resolution should be done separately\n */\nexport async function finishDecoding(\n transaction: DecoderResult,\n options: ServerDecoderOptions,\n caches: ServerDecoderCaches\n): Promise<DecoderResult> {\n const startTime = Date.now()\n const { chain } = options\n\n try {\n // Check cache first\n const txHash = transaction.hash || transaction.transactionHash\n if (txHash) {\n const cached = caches.getTransaction(txHash)\n if (cached?.enhancementAttempted) {\n return {\n ...cached,\n cached: true,\n timeTaken: 0,\n } as DecoderResult\n }\n }\n\n // Get all plugins\n const allPlugins = await pluginRegistry.getAll()\n const schemaPlugins = pluginRegistry.getAllSchema()\n\n const enhancedOptions = {\n chain,\n plugins: allPlugins,\n schemaPlugins,\n wrappers: [],\n async: true,\n }\n\n // Wrappers and children must be removed when finishing decoding, because otherwise\n // the decoder will build hierarchical structures which are infinite.\n const {\n wrappers,\n children: _children,\n addresses: _addresses,\n ...transactionWithoutWrappers\n } = transaction as DecoderResult & {\n children?: unknown[]\n wrappers?: unknown[]\n addresses?: unknown[]\n }\n\n // Simply pass the entire transaction hierarchy to decodeTransactionCore\n // It will handle children properly and return a fully enhanced copy\n const enhancedResult = await decodeTransactionCore(\n transactionWithoutWrappers as DecoderResult,\n enhancedOptions\n )\n\n if (!enhancedResult) {\n if (txHash) {\n caches.setTransaction(txHash, {\n ...transaction,\n enhancementAttempted: true,\n })\n }\n return transaction\n }\n\n const result = {\n ...enhancedResult,\n // Only add wrappers if there are any\n ...((wrappers?.length || 0) > 0 ? { wrappers } : {}),\n cached: false,\n timeTaken: Date.now() - startTime,\n enhancementAttempted: true,\n } as DecoderResult\n\n // Always update cache with the enhanced result\n if (txHash) {\n caches.setTransaction(txHash, result)\n }\n\n return result\n } catch (error) {\n console.error('Failed to finish decoding transaction:', error)\n return {\n ...createErrorResult(transaction),\n phase: 'immediate',\n cached: false,\n timeTaken: Date.now() - startTime,\n }\n }\n}\n\nfunction createErrorResult(transaction: DecoderResult): DecoderResult {\n return {\n ...transaction,\n resultType: 'error',\n errorType: 'UNKNOWN',\n sig: '0x' as `0x${string}`,\n addresses: [],\n } as DecoderResult\n}\n","import { ServerAddressResolver } from './addressResolver'\nimport { ServerDecoderCaches } from './caches'\nimport { decodeTransactionSync } from './decodeTransactionSync'\nimport { decodeTransactionsBatch } from './decodeTransactionsBatch'\nimport { finishDecoding } from './finishDecoding'\nimport type {\n ServerDecoder,\n ServerDecoderConfig,\n ServerDecoderOptions,\n} from './types'\n\n// Import plugins to ensure they are registered\nimport '../decoder/plugins'\n\n/**\n * Create a server-optimized decoder instance\n */\nexport function createServerDecoder(\n config: ServerDecoderConfig\n): ServerDecoder {\n // Create caches\n const caches = new ServerDecoderCaches({\n transactionCacheSize: config.transactionCacheSize,\n addressCacheSize: config.addressCacheSize,\n abiCacheSize: config.abiCacheSize,\n schemaCacheSize: config.schemaCacheSize,\n })\n\n // Create address resolver\n const addressResolver = new ServerAddressResolver(\n config.graphqlEndpoint,\n config.defaultChain,\n caches\n )\n\n // Return server decoder interface\n return {\n async decodeTransaction(transaction, options) {\n const opts: ServerDecoderOptions = {\n chain: config.defaultChain,\n timeoutMs: config.defaultTimeout,\n ...options,\n }\n return decodeTransactionSync(transaction, opts, caches)\n },\n\n async decodeTransactionsBatch(transactions, options) {\n const opts: ServerDecoderOptions = {\n chain: config.defaultChain,\n timeoutMs: config.defaultTimeout,\n ...options,\n }\n return decodeTransactionsBatch(transactions, opts, caches)\n },\n\n async finishDecoding(transaction, options) {\n const opts: ServerDecoderOptions = {\n chain: config.defaultChain,\n timeoutMs: config.defaultTimeout,\n ...options,\n }\n return finishDecoding(transaction, opts, caches)\n },\n\n clearCaches() {\n caches.clear()\n },\n\n getCacheStats() {\n return caches.getStats()\n },\n\n async warmAddressCache(addresses) {\n await addressResolver.warmCache(addresses)\n },\n\n async resolveAddresses(addresses, timeoutMs = 3000) {\n return addressResolver.resolveAddressesWithTimeout(addresses, timeoutMs)\n },\n }\n}\n"],"mappings":"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","names":["createErrorResult","createErrorResult"]}
|
|
1
|
+
{"version":3,"sources":["../src/server/addressResolver.ts","../src/server/caches.ts","../src/server/decodeEventLogs.ts","../src/server/decodeTransactionSync.ts","../src/server/decodeTransactionsBatch.ts","../src/server/finishDecoding.ts","../src/server/index.ts"],"sourcesContent":["import type { Chain } from 'viem'\nimport { fetchMultipleAddresses } from '../shared/addressResolver'\nimport type { AddressIdentityCache } from '../shared/cache'\nimport type { DataKey, EnhancedInfo } from '../types'\nimport type { ServerDecoderCaches } from './caches'\n\n/**\n * Server-side address resolver with caching\n */\nexport class ServerAddressResolver {\n private cacheAdapter: AddressIdentityCache\n\n constructor(\n private graphqlEndpoint: string,\n _chain: Chain,\n private caches: ServerDecoderCaches\n ) {\n // Create adapter to use ServerDecoderCaches as AddressIdentityCache\n this.cacheAdapter = {\n get: (key: DataKey) => this.caches.getAddress(key),\n set: (key: DataKey, value: EnhancedInfo) =>\n this.caches.setAddress(key, value),\n has: (key: DataKey) => this.caches.hasAddress(key),\n getMany: (keys: DataKey[]) => this.caches.getAddresses(keys),\n }\n }\n\n /**\n * Resolve addresses, using cache when possible\n */\n async resolveAddresses(\n addresses: readonly DataKey[]\n ): Promise<Map<DataKey, EnhancedInfo>> {\n // Use the shared implementation with cache adapter\n return fetchMultipleAddresses(\n addresses,\n this.graphqlEndpoint,\n this.cacheAdapter\n )\n }\n\n /**\n * Resolve addresses with timeout\n */\n async resolveAddressesWithTimeout(\n addresses: DataKey[],\n timeoutMs: number\n ): Promise<Map<DataKey, EnhancedInfo>> {\n return Promise.race([\n this.resolveAddresses(addresses),\n new Promise<Map<DataKey, EnhancedInfo>>((resolve) => {\n setTimeout(() => {\n // On timeout, return whatever we have cached\n const results = this.caches.getAddresses(addresses)\n resolve(results)\n }, timeoutMs)\n }),\n ])\n }\n\n /**\n * Warm the cache with specific addresses\n */\n async warmCache(addresses: DataKey[]): Promise<void> {\n // Simply call resolveAddresses which will cache any uncached addresses\n await this.resolveAddresses(addresses)\n }\n}\n","import { LRUCache } from 'lru-cache'\nimport type { Abi } from 'viem'\nimport type { DecoderResult, Info } from '../decoder/types'\nimport type { DataKey, EnhancedInfo } from '../types'\nimport type { CacheStats } from './types'\n\n/**\n * Multi-level caching system for server-side decoder\n */\nexport class ServerDecoderCaches {\n // Level 1: Decoded transaction cache (keyed by transaction hash)\n private transactionCache: LRUCache<string, DecoderResult>\n private transactionStats = { hits: 0, misses: 0 }\n\n // Level 2: Address metadata cache (keyed by address or address:tokenId)\n private addressCache: LRUCache<string, EnhancedInfo>\n private addressStats = { hits: 0, misses: 0 }\n\n // Level 3: Contract ABI cache (keyed by address)\n private abiCache: LRUCache<string, Abi>\n private abiStats = { hits: 0, misses: 0 }\n\n // Level 4: Schema decode cache (keyed by key:value)\n private schemaCache: LRUCache<string, Info>\n private schemaStats = { hits: 0, misses: 0 }\n\n constructor(\n options: {\n transactionCacheSize?: number\n addressCacheSize?: number\n abiCacheSize?: number\n schemaCacheSize?: number\n } = {}\n ) {\n // Transaction cache - store complete decoded results\n this.transactionCache = new LRUCache<string, DecoderResult>({\n max: options.transactionCacheSize || 10000,\n ttl: 1000 * 60 * 60, // 1 hour TTL\n updateAgeOnGet: true,\n updateAgeOnHas: true,\n })\n\n // Address cache - store profile/asset metadata\n this.addressCache = new LRUCache<string, EnhancedInfo>({\n max: options.addressCacheSize || 50000,\n ttl: 1000 * 60 * 60 * 24, // 24 hour TTL\n updateAgeOnGet: true,\n updateAgeOnHas: true,\n })\n\n // ABI cache - store contract ABIs\n this.abiCache = new LRUCache<string, Abi>({\n max: options.abiCacheSize || 5000,\n ttl: 1000 * 60 * 60 * 24 * 7, // 7 day TTL (ABIs rarely change)\n updateAgeOnGet: true,\n updateAgeOnHas: true,\n })\n\n // Schema cache - store decoded schema values\n this.schemaCache = new LRUCache<string, Info>({\n max: options.schemaCacheSize || 10000,\n ttl: 1000 * 60 * 60, // 1 hour TTL\n updateAgeOnGet: true,\n updateAgeOnHas: true,\n })\n }\n\n /**\n * Get cache key for a data key (address or address:tokenId)\n */\n private getDataKeyCacheKey(key: DataKey): string {\n return key.toLowerCase()\n }\n\n // Transaction cache methods\n getTransaction(hash: string): DecoderResult | undefined {\n const result = this.transactionCache.get(hash.toLowerCase())\n if (result) {\n this.transactionStats.hits++\n return { ...result, cached: true }\n }\n this.transactionStats.misses++\n return undefined\n }\n\n setTransaction(hash: string, result: DecoderResult): void {\n this.transactionCache.set(hash.toLowerCase(), result)\n }\n\n // Address cache methods\n getAddress(key: DataKey): EnhancedInfo | undefined {\n const cacheKey = this.getDataKeyCacheKey(key)\n const result = this.addressCache.get(cacheKey)\n if (result) {\n this.addressStats.hits++\n return result\n }\n this.addressStats.misses++\n return undefined\n }\n\n setAddress(key: DataKey, data: EnhancedInfo): void {\n const cacheKey = this.getDataKeyCacheKey(key)\n this.addressCache.set(cacheKey, data)\n }\n\n hasAddress(key: DataKey): boolean {\n return this.addressCache.has(this.getDataKeyCacheKey(key))\n }\n\n getAddresses(keys: DataKey[]): Map<DataKey, EnhancedInfo> {\n const results = new Map<DataKey, EnhancedInfo>()\n for (const key of keys) {\n const data = this.getAddress(key)\n if (data) {\n results.set(key, data)\n }\n }\n return results\n }\n\n // ABI cache methods\n getAbi(address: string): Abi | undefined {\n const result = this.abiCache.get(address.toLowerCase())\n if (result) {\n this.abiStats.hits++\n return result\n }\n this.abiStats.misses++\n return undefined\n }\n\n setAbi(address: string, abi: Abi): void {\n this.abiCache.set(address.toLowerCase(), abi)\n }\n\n hasAbi(address: string): boolean {\n return this.abiCache.has(address.toLowerCase())\n }\n\n // Schema cache methods\n getSchema(key: string, value: string): Info | undefined {\n const cacheKey = `${key}:${value}`\n const result = this.schemaCache.get(cacheKey)\n if (result) {\n this.schemaStats.hits++\n return result\n }\n this.schemaStats.misses++\n return undefined\n }\n\n setSchema(key: string, value: string, info: Info): void {\n const cacheKey = `${key}:${value}`\n this.schemaCache.set(cacheKey, info)\n }\n\n // Cache management\n clear(): void {\n this.transactionCache.clear()\n this.addressCache.clear()\n this.abiCache.clear()\n this.schemaCache.clear()\n\n // Reset stats\n this.transactionStats = { hits: 0, misses: 0 }\n this.addressStats = { hits: 0, misses: 0 }\n this.abiStats = { hits: 0, misses: 0 }\n this.schemaStats = { hits: 0, misses: 0 }\n }\n\n getStats(): CacheStats {\n const calculateHitRate = (stats: { hits: number; misses: number }) => {\n const total = stats.hits + stats.misses\n return total > 0 ? stats.hits / total : 0\n }\n\n return {\n transactions: {\n size: this.transactionCache.size,\n maxSize: this.transactionCache.max,\n hits: this.transactionStats.hits,\n misses: this.transactionStats.misses,\n hitRate: calculateHitRate(this.transactionStats),\n },\n addresses: {\n size: this.addressCache.size,\n maxSize: this.addressCache.max,\n hits: this.addressStats.hits,\n misses: this.addressStats.misses,\n hitRate: calculateHitRate(this.addressStats),\n },\n abis: {\n size: this.abiCache.size,\n maxSize: this.abiCache.max,\n hits: this.abiStats.hits,\n misses: this.abiStats.misses,\n hitRate: calculateHitRate(this.abiStats),\n },\n schemas: {\n size: this.schemaCache.size,\n maxSize: this.schemaCache.max,\n hits: this.schemaStats.hits,\n misses: this.schemaStats.misses,\n hitRate: calculateHitRate(this.schemaStats),\n },\n }\n }\n}\n","import type { Hex } from 'viem'\nimport { decodeKeyValueRaw } from '../decoder/plugins'\nimport { pluginRegistry } from '../decoder/registry'\nimport type { DecodeEventResult, DecoderOptions } from '../decoder/types'\nimport type { ServerDecoderCaches } from './caches'\nimport type { ServerDecoderOptions } from './types'\n\n/**\n * Decode an array of raw log events using the registered decoder plugins.\n *\n * Uses the same plugin iteration pattern as transaction.ts:\n * try each plugin's `decodeEvent`, first match wins, raw log kept as fallback.\n *\n * For DataChanged events, also decodes the ERC725Y key-value pair using\n * the schema plugin system (same as setData transaction decoding).\n */\nexport async function decodeEventLogs(\n logs: DecodeEventResult[],\n options: ServerDecoderOptions,\n _caches: ServerDecoderCaches\n): Promise<DecodeEventResult[]> {\n const { chain } = options\n const plugins = await pluginRegistry.getAll({ syncOnly: true })\n const schemaPlugins = pluginRegistry.getAllSchema()\n\n const decoderOptions: DecoderOptions = {\n chain,\n plugins,\n schemaPlugins,\n wrappers: [],\n async: false,\n }\n\n const results: DecodeEventResult[] = []\n\n for (const log of logs) {\n let decoded: DecodeEventResult\n for (const plugin of plugins) {\n decoded = await plugin.decodeEvent(log, decoderOptions)\n if (decoded) break\n }\n const result = decoded ?? log\n\n // For DataChanged events, decode the ERC725Y key-value pair\n if (result?.eventName === 'DataChanged' && result.args) {\n try {\n const dataKey = result.args.find((a) => a.name === 'dataKey')?.value as\n | Hex\n | undefined\n const dataValue = result.args.find((a) => a.name === 'dataValue')\n ?.value as Hex | undefined\n if (dataKey) {\n const info = await decodeKeyValueRaw(\n dataKey,\n dataValue ?? '0x',\n decoderOptions\n )\n if (info) {\n ;(result as Record<string, unknown>).info = info\n }\n }\n } catch {\n // Schema decoding failed — keep event without info\n }\n }\n\n results.push(result)\n }\n\n return results\n}\n","import { collectDataKeys } from '../core/addressCollector'\nimport { pluginRegistry } from '../decoder/registry'\nimport { decodeTransaction as decodeTransactionCore } from '../decoder/transaction'\nimport type { DecoderResult } from '../decoder/types'\nimport { needsEnhancement } from '../decoder/utils'\nimport type { ServerDecoderCaches } from './caches'\nimport type { ServerDecoderOptions } from './types'\n\n/**\n * Decode a single transaction with time-bounded enhancement\n */\nexport async function decodeTransactionSync(\n transaction: DecoderResult,\n options: ServerDecoderOptions,\n caches: ServerDecoderCaches\n): Promise<DecoderResult> {\n const startTime = Date.now()\n const { timeoutMs = 800, enableEnhancement = true, chain } = options\n\n // Check transaction cache first\n if (transaction.hash) {\n const cached = caches.getTransaction(transaction.hash)\n if (cached) {\n return cached\n }\n }\n\n try {\n // Phase 1: Immediate decode (sync plugins only)\n const phase1Start = Date.now()\n const plugins = await pluginRegistry.getAll({ syncOnly: true })\n const schemaPlugins = pluginRegistry.getAllSchema()\n\n const immediateOptions = {\n chain,\n plugins,\n schemaPlugins,\n wrappers: [],\n async: false,\n }\n const immediateResult = await decodeTransactionCore(\n transaction,\n immediateOptions\n )\n\n if (!immediateResult) {\n return {\n ...createErrorResult(transaction),\n phase: 'immediate',\n cached: false,\n timeTaken: Date.now() - startTime,\n }\n }\n\n let currentResult: DecoderResult = immediateResult\n let phase: 'immediate' | 'enhanced' | 'complete' = 'immediate'\n\n // Transfer collected wrappers if any\n if (immediateOptions.wrappers.length > 0) {\n ;(currentResult as any).wrappers = immediateOptions.wrappers\n }\n\n // Collect addresses from the decoded result\n const addresses = collectDataKeys(currentResult)\n currentResult.addresses = addresses\n\n // Check if we have time for enhancement\n const phase1Time = Date.now() - phase1Start\n if (enableEnhancement && phase1Time < timeoutMs * 0.6) {\n // Check if enhancement is actually needed\n if (!needsEnhancement(currentResult)) {\n // Already fully decoded during immediate phase\n phase = 'enhanced'\n } else {\n // Phase 2: Enhancement with async plugins\n try {\n const allPlugins = await pluginRegistry.getAll()\n const enhancedOptions = {\n chain,\n plugins: allPlugins,\n schemaPlugins,\n wrappers: [],\n async: true,\n }\n const enhancedResult = await Promise.race([\n decodeTransactionCore(transaction, enhancedOptions),\n // Timeout for phase 2\n new Promise<null>((resolve) =>\n setTimeout(() => resolve(null), timeoutMs * 0.6 - phase1Time)\n ),\n ])\n\n if (enhancedResult) {\n currentResult = enhancedResult\n phase = 'enhanced'\n\n // Merge wrappers from both phases (immediate + enhanced)\n const allWrappers = [\n ...((immediateOptions.wrappers || []) as any[]),\n ...(enhancedOptions.wrappers || []),\n ].filter(\n (w, i, arr) =>\n // Deduplicate by checking if this is the first occurrence\n arr.findIndex(\n (x) => JSON.stringify(x) === JSON.stringify(w)\n ) === i\n )\n\n if (allWrappers.length > 0) {\n ;(currentResult as any).wrappers = allWrappers\n }\n\n // Re-collect addresses from enhanced result\n currentResult.addresses = collectDataKeys(currentResult)\n }\n } catch (error) {\n console.error('Enhancement failed:', error)\n }\n }\n }\n\n const result: DecoderResult = {\n ...currentResult,\n phase,\n cached: false,\n timeTaken: Date.now() - startTime,\n }\n\n // Cache the result if we have a hash\n if (transaction.hash) {\n caches.setTransaction(transaction.hash, result)\n }\n\n return result\n } catch (error) {\n console.error('Failed to decode transaction:', error)\n return {\n ...createErrorResult(transaction),\n phase: 'immediate',\n cached: false,\n timeTaken: Date.now() - startTime,\n }\n }\n}\n\nfunction createErrorResult(transaction: DecoderResult): DecoderResult {\n return {\n ...transaction,\n isDecoded: false,\n resultType: 'error',\n errorType: 'UNKNOWN',\n sig: '0x' as `0x${string}`,\n addresses: [],\n } as DecoderResult\n}\n","import { collectDataKeys } from '../core/addressCollector'\nimport { pluginRegistry } from '../decoder/registry'\nimport { decodeTransaction as decodeTransactionCore } from '../decoder/transaction'\nimport type { DecoderResult, ResultShared } from '../decoder/types'\nimport { needsEnhancement } from '../decoder/utils'\nimport type { ServerDecoderCaches } from './caches'\nimport type { BatchDecodeResult, ServerDecoderOptions } from './types'\n\n/**\n * Decode multiple transactions with batching and time budget\n */\nexport async function decodeTransactionsBatch(\n transactions: DecoderResult[],\n options: ServerDecoderOptions,\n caches: ServerDecoderCaches\n): Promise<BatchDecodeResult> {\n const startTime = Date.now()\n const { timeoutMs = 800, enableEnhancement = true, chain } = options\n\n // Step 1: Check cache for all transactions\n const results: (DecoderResult | null)[] = transactions.map((tx) => {\n if (tx.transactionHash) {\n const cached = caches.getTransaction(tx.transactionHash)\n if (cached) return cached\n }\n return null\n })\n\n // Find uncached transactions\n const uncachedIndexes: number[] = []\n const uncachedTransactions: DecoderResult[] = []\n results.forEach((result, index) => {\n if (!result) {\n uncachedIndexes.push(index)\n uncachedTransactions.push(transactions[index])\n }\n })\n\n // If all are cached, return early\n if (uncachedTransactions.length === 0) {\n return {\n results: results as DecoderResult[],\n }\n }\n\n try {\n // Get plugins once for all transactions\n const syncPlugins = await pluginRegistry.getAll({ syncOnly: true })\n const allPlugins = await pluginRegistry.getAll()\n const schemaPlugins = pluginRegistry.getAllSchema()\n\n // Phase 1: Immediate decode for all uncached transactions\n const phase1Start = Date.now()\n const immediateOptionsArray = uncachedTransactions.map(() => ({\n chain,\n plugins: syncPlugins,\n schemaPlugins,\n wrappers: [],\n async: false,\n }))\n\n const immediateResults: DecoderResult[] = (\n await Promise.all(\n uncachedTransactions.map(async (tx, i) => {\n return await decodeTransactionCore(tx, immediateOptionsArray[i])\n })\n )\n ).filter(Boolean) as DecoderResult[]\n\n // Create result objects and collect addresses\n const newResults: DecoderResult[] = immediateResults\n .map((result, i) => {\n const data = result || createErrorResult(uncachedTransactions[i])\n\n // Transfer wrappers from immediate phase options\n if (immediateOptionsArray[i].wrappers.length > 0) {\n ;(data as any).wrappers = immediateOptionsArray[i].wrappers\n }\n\n // Collect addresses from the decoded result\n data.addresses = collectDataKeys(data)\n ;(data as ResultShared).timeTaken = Date.now() - startTime\n return data\n })\n .filter(Boolean) as DecoderResult[]\n\n // Check if we have time for enhancement\n const phase1Time = Date.now() - phase1Start\n if (enableEnhancement && phase1Time < timeoutMs * 0.6) {\n // Phase 2: Enhancement with async plugins (batch all transactions)\n try {\n const enhancedOptionsArray = uncachedTransactions.map(() => ({\n chain,\n plugins: allPlugins,\n schemaPlugins,\n wrappers: [],\n async: true,\n }))\n\n const enhancePromises = uncachedTransactions.map((tx, i) => {\n // Only enhance if immediate decode succeeded\n if (!immediateResults[i]) return null\n\n // Check if enhancement is actually needed\n if (!needsEnhancement(immediateResults[i])) {\n // Already fully decoded during immediate phase\n return null\n }\n\n return decodeTransactionCore(tx, enhancedOptionsArray[i])\n })\n\n // Wait for all enhancements with remaining time budget\n const _remainingTime = timeoutMs * 0.6 - phase1Time\n const enhancedResults = await Promise.all(enhancePromises)\n\n // Update results with enhanced data\n enhancedResults.forEach((enhanced, i) => {\n if (enhanced) {\n // Merge wrappers from both phases (immediate + enhanced)\n const immediateWrappers = immediateOptionsArray[i].wrappers || []\n const enhancedWrappers = enhancedOptionsArray[i].wrappers || []\n const allWrappers = [\n ...immediateWrappers,\n ...enhancedWrappers,\n ].filter(\n (w, idx, arr) =>\n // Deduplicate by checking if this is the first occurrence\n arr.findIndex(\n (x) => JSON.stringify(x) === JSON.stringify(w)\n ) === idx\n )\n\n // Enhancement returned a new result\n newResults[i] = enhanced\n\n // Add merged wrappers if any\n if (allWrappers.length > 0) {\n ;(newResults[i] as any).wrappers = allWrappers\n }\n\n // Re-collect addresses from enhanced result\n newResults[i].addresses = collectDataKeys(enhanced)\n newResults[i].phase = 'enhanced'\n } else if (\n immediateResults[i] &&\n !needsEnhancement(immediateResults[i])\n ) {\n // Enhancement was skipped because already fully decoded\n newResults[i].phase = 'enhanced'\n }\n })\n } catch (error) {\n console.error('Batch enhancement failed:', error)\n }\n }\n\n // Update timings\n const totalTime = Date.now() - startTime\n newResults.forEach((result) => {\n result.timeTaken = totalTime\n })\n\n // Cache all new results\n newResults.forEach((result, i) => {\n const tx = uncachedTransactions[i]\n if (tx.hash) {\n caches.setTransaction(tx.hash, result)\n }\n })\n\n // Merge cached and new results\n uncachedIndexes.forEach((originalIndex, i) => {\n results[originalIndex] = newResults[i]\n })\n\n return {\n results: results as DecoderResult[],\n }\n } catch (error) {\n console.error('Batch decode failed:', error)\n // Return error results for uncached transactions\n uncachedIndexes.forEach((originalIndex) => {\n results[originalIndex] = {\n ...createErrorResult(transactions[originalIndex]),\n phase: 'immediate',\n cached: false,\n timeTaken: Date.now() - startTime,\n }\n })\n\n return {\n results: results as DecoderResult[],\n }\n }\n}\n\nfunction createErrorResult(transaction: DecoderResult): DecoderResult {\n return {\n ...transaction,\n isDecoded: false,\n resultType: 'error',\n errorType: 'UNKNOWN',\n sig: '0x' as `0x${string}`,\n addresses: [],\n } as DecoderResult\n}\n","import { pluginRegistry } from '../decoder/registry'\nimport { decodeTransaction as decodeTransactionCore } from '../decoder/transaction'\nimport type { DecoderResult } from '../decoder/types'\nimport { createDebug } from '../utils/debug'\nimport type { ServerDecoderCaches } from './caches'\nimport type { ServerDecoderOptions } from './types'\n\nconst _debug = createDebug('decoder:finishDecoding')\n\n/**\n * Finish decoding a transaction by running enhancement phase\n * This only does phase 2 (async plugins) - address resolution should be done separately\n */\nexport async function finishDecoding(\n transaction: DecoderResult,\n options: ServerDecoderOptions,\n caches: ServerDecoderCaches\n): Promise<DecoderResult> {\n const startTime = Date.now()\n const { chain } = options\n\n try {\n // Check cache first\n const txHash = transaction.hash || transaction.transactionHash\n if (txHash) {\n const cached = caches.getTransaction(txHash)\n if (cached?.enhancementAttempted) {\n return {\n ...cached,\n cached: true,\n timeTaken: 0,\n } as DecoderResult\n }\n }\n\n // Get all plugins\n const allPlugins = await pluginRegistry.getAll()\n const schemaPlugins = pluginRegistry.getAllSchema()\n\n const enhancedOptions = {\n chain,\n plugins: allPlugins,\n schemaPlugins,\n wrappers: [],\n async: true,\n }\n\n // Wrappers and children must be removed when finishing decoding, because otherwise\n // the decoder will build hierarchical structures which are infinite.\n const {\n wrappers,\n children: _children,\n addresses: _addresses,\n ...transactionWithoutWrappers\n } = transaction as DecoderResult & {\n children?: unknown[]\n wrappers?: unknown[]\n addresses?: unknown[]\n }\n\n // Simply pass the entire transaction hierarchy to decodeTransactionCore\n // It will handle children properly and return a fully enhanced copy\n const enhancedResult = await decodeTransactionCore(\n transactionWithoutWrappers as DecoderResult,\n enhancedOptions\n )\n\n if (!enhancedResult) {\n if (txHash) {\n caches.setTransaction(txHash, {\n ...transaction,\n enhancementAttempted: true,\n })\n }\n return transaction\n }\n\n const result = {\n ...enhancedResult,\n // Only add wrappers if there are any\n ...((wrappers?.length || 0) > 0 ? { wrappers } : {}),\n cached: false,\n timeTaken: Date.now() - startTime,\n enhancementAttempted: true,\n } as DecoderResult\n\n // Always update cache with the enhanced result\n if (txHash) {\n caches.setTransaction(txHash, result)\n }\n\n return result\n } catch (error) {\n console.error('Failed to finish decoding transaction:', error)\n return {\n ...createErrorResult(transaction),\n phase: 'immediate',\n cached: false,\n timeTaken: Date.now() - startTime,\n }\n }\n}\n\nfunction createErrorResult(transaction: DecoderResult): DecoderResult {\n return {\n ...transaction,\n resultType: 'error',\n errorType: 'UNKNOWN',\n sig: '0x' as `0x${string}`,\n addresses: [],\n } as DecoderResult\n}\n","import { ServerAddressResolver } from './addressResolver'\nimport { ServerDecoderCaches } from './caches'\nimport { decodeEventLogs } from './decodeEventLogs'\nimport { decodeTransactionSync } from './decodeTransactionSync'\nimport { decodeTransactionsBatch } from './decodeTransactionsBatch'\nimport { finishDecoding } from './finishDecoding'\nimport type {\n ServerDecoder,\n ServerDecoderConfig,\n ServerDecoderOptions,\n} from './types'\n\n// Import plugins to ensure they are registered\nimport '../decoder/plugins'\n\n/**\n * Create a server-optimized decoder instance\n */\nexport function createServerDecoder(\n config: ServerDecoderConfig\n): ServerDecoder {\n // Create caches\n const caches = new ServerDecoderCaches({\n transactionCacheSize: config.transactionCacheSize,\n addressCacheSize: config.addressCacheSize,\n abiCacheSize: config.abiCacheSize,\n schemaCacheSize: config.schemaCacheSize,\n })\n\n // Create address resolver\n const addressResolver = new ServerAddressResolver(\n config.graphqlEndpoint,\n config.defaultChain,\n caches\n )\n\n // Return server decoder interface\n return {\n async decodeTransaction(transaction, options) {\n const opts: ServerDecoderOptions = {\n chain: config.defaultChain,\n timeoutMs: config.defaultTimeout,\n ...options,\n }\n return decodeTransactionSync(transaction, opts, caches)\n },\n\n async decodeTransactionsBatch(transactions, options) {\n const opts: ServerDecoderOptions = {\n chain: config.defaultChain,\n timeoutMs: config.defaultTimeout,\n ...options,\n }\n return decodeTransactionsBatch(transactions, opts, caches)\n },\n\n async finishDecoding(transaction, options) {\n const opts: ServerDecoderOptions = {\n chain: config.defaultChain,\n timeoutMs: config.defaultTimeout,\n ...options,\n }\n return finishDecoding(transaction, opts, caches)\n },\n\n clearCaches() {\n caches.clear()\n },\n\n getCacheStats() {\n return caches.getStats()\n },\n\n async warmAddressCache(addresses) {\n await addressResolver.warmCache(addresses)\n },\n\n async resolveAddresses(addresses, timeoutMs = 3000) {\n return addressResolver.resolveAddressesWithTimeout(addresses, timeoutMs)\n },\n\n async decodeEventLogs(logs, options) {\n const opts: ServerDecoderOptions = {\n chain: config.defaultChain,\n timeoutMs: config.defaultTimeout,\n ...options,\n }\n return decodeEventLogs(logs, opts, caches)\n },\n }\n}\n"],"mappings":"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","names":["createErrorResult","createErrorResult"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { g as IDataModelConsumer, I as IDataModel,
|
|
1
|
+
import { g as IDataModelConsumer, I as IDataModel, b as DataKey, c as DecoderResult, T as TransactionState, h as DecoderOptions, P as PluginOptions, i as EnhancerCallback, j as DecodeEventCallback, k as EnhancerAggregationKeyCallback, l as EnhancerSummarizeCallback, m as Aggregation, n as DecoderPlugin, e as Info, S as SchemaPlugin, o as ResultSetData, A as ArrayArgs, C as CustomDecodeFunctionDataReturn, E as EnhancedInfo } from './index-BWD9DaG6.js';
|
|
2
2
|
import { Signal } from '@preact/signals-core';
|
|
3
3
|
import { Transaction, Abi, Hex, AbiParameter, DecodeFunctionDataParameters, Address, Chain, PublicClient } from 'viem';
|
|
4
4
|
import { ERC725JSONSchema } from '@erc725/erc725.js';
|
|
@@ -105,4 +105,4 @@ declare function getPublicClient(chain: Chain): PublicClient;
|
|
|
105
105
|
*/
|
|
106
106
|
declare function needsEnhancement(result: DecoderResult): boolean;
|
|
107
107
|
|
|
108
|
-
export { type AddressResolver as A, type TransactionDecoderResult as T,
|
|
108
|
+
export { type AddressResolver as A, type TransactionDecoderResult as T, customDecodeFunctionData as a, decodeKeyValue as b, createNamedArgs as c, dataModel as d, decodeKeyValueRaw as e, decodeTransaction as f, extractAddress as g, getPublicClient as h, consumerModel as i, createAggregationKey as j, createGlobalInstance as k, decodeTransactionAsync as l, defaultPlugins as m, defaultSchemaPlugins as n, getArgByName as o, needsEnhancement as p, standardPlugin as q, standardSchemaPlugin as s };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { g as IDataModelConsumer, I as IDataModel,
|
|
1
|
+
import { g as IDataModelConsumer, I as IDataModel, b as DataKey, c as DecoderResult, T as TransactionState, h as DecoderOptions, P as PluginOptions, i as EnhancerCallback, j as DecodeEventCallback, k as EnhancerAggregationKeyCallback, l as EnhancerSummarizeCallback, m as Aggregation, n as DecoderPlugin, e as Info, S as SchemaPlugin, o as ResultSetData, A as ArrayArgs, C as CustomDecodeFunctionDataReturn, E as EnhancedInfo } from './index-BWD9DaG6.cjs';
|
|
2
2
|
import { Signal } from '@preact/signals-core';
|
|
3
3
|
import { Transaction, Abi, Hex, AbiParameter, DecodeFunctionDataParameters, Address, Chain, PublicClient } from 'viem';
|
|
4
4
|
import { ERC725JSONSchema } from '@erc725/erc725.js';
|
|
@@ -105,4 +105,4 @@ declare function getPublicClient(chain: Chain): PublicClient;
|
|
|
105
105
|
*/
|
|
106
106
|
declare function needsEnhancement(result: DecoderResult): boolean;
|
|
107
107
|
|
|
108
|
-
export { type AddressResolver as A, type TransactionDecoderResult as T,
|
|
108
|
+
export { type AddressResolver as A, type TransactionDecoderResult as T, customDecodeFunctionData as a, decodeKeyValue as b, createNamedArgs as c, dataModel as d, decodeKeyValueRaw as e, decodeTransaction as f, extractAddress as g, getPublicClient as h, consumerModel as i, createAggregationKey as j, createGlobalInstance as k, decodeTransactionAsync as l, defaultPlugins as m, defaultSchemaPlugins as n, getArgByName as o, needsEnhancement as p, standardPlugin as q, standardSchemaPlugin as s };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lukso/transaction-decoder",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.7-dev.2df3eae",
|
|
4
4
|
"description": "Transaction decoder for LUKSO blockchain with reactive state management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -47,19 +47,19 @@
|
|
|
47
47
|
"@lukso/lsp8-contracts": "0.16.7",
|
|
48
48
|
"@lukso/lsp9-contracts": "0.15.5",
|
|
49
49
|
"@lukso/universalprofile-contracts": "0.15.5",
|
|
50
|
-
"@preact/signals-core": "^1.
|
|
50
|
+
"@preact/signals-core": "^1.13.0",
|
|
51
51
|
"graphql-request": "^7.4.0",
|
|
52
|
-
"graphql-ws": "^6.0.
|
|
53
|
-
"lru-cache": "^11.2.
|
|
54
|
-
"viem": "^2.
|
|
52
|
+
"graphql-ws": "^6.0.7",
|
|
53
|
+
"lru-cache": "^11.2.6",
|
|
54
|
+
"viem": "^2.46.1"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
|
-
"@biomejs/biome": "^2.
|
|
57
|
+
"@biomejs/biome": "^2.4.2",
|
|
58
58
|
"@types/debug": "^4.1.12",
|
|
59
|
-
"@types/node": "^25.
|
|
59
|
+
"@types/node": "^25.2.3",
|
|
60
60
|
"tsup": "^8.5.1",
|
|
61
61
|
"typescript": "^5.9.3",
|
|
62
|
-
"vitest": "^4.0.
|
|
62
|
+
"vitest": "^4.0.18"
|
|
63
63
|
},
|
|
64
64
|
"peerDependencies": {
|
|
65
65
|
"viem": "^2.0.0"
|
|
@@ -145,24 +145,31 @@ describe('LSP7 Mint Transaction Decoding', () => {
|
|
|
145
145
|
expect(dataChangedLogs.length).toBeGreaterThan(0)
|
|
146
146
|
console.log(`\nFound ${dataChangedLogs.length} DataChanged events`)
|
|
147
147
|
|
|
148
|
-
// Look for
|
|
149
|
-
// UniversalReceiver
|
|
150
|
-
const
|
|
151
|
-
(log: any) =>
|
|
148
|
+
// Look for unwrapped URDTokensReceived event from UniversalReceiver (confirms the mint was received)
|
|
149
|
+
// The UniversalReceiver event is now unwrapped into URDTokensReceived with standard: LSP7DigitalAsset
|
|
150
|
+
const unwrappedTransferLog = result?.logs?.find(
|
|
151
|
+
(log: any) =>
|
|
152
|
+
log.eventName === 'URDTokensReceived' &&
|
|
153
|
+
log.standard === 'LSP7DigitalAsset'
|
|
152
154
|
)
|
|
153
|
-
expect(
|
|
154
|
-
expect(
|
|
155
|
+
expect(unwrappedTransferLog).toBeDefined()
|
|
156
|
+
expect(unwrappedTransferLog?.address).toBe(
|
|
155
157
|
'0xda9b727f1718f128008ad025828e7fecfaa8a37b'
|
|
156
158
|
) // LSP7 token contract
|
|
157
159
|
|
|
158
|
-
// Verify the UniversalReceiver
|
|
159
|
-
|
|
160
|
-
expect(
|
|
160
|
+
// Verify the original UniversalReceiver is preserved in wrappers
|
|
161
|
+
const wrapper = (unwrappedTransferLog as any)?.wrappers?.[0]
|
|
162
|
+
expect(wrapper).toBeDefined()
|
|
163
|
+
expect(wrapper?.eventName).toBe('UniversalReceiver')
|
|
164
|
+
|
|
165
|
+
// Verify the UniversalReceiver typeId indicates this is a mint recipient notification
|
|
166
|
+
// typeId 0x20804611b3e2ea21c480dc465142210acf4a2485947541770ec1fb87dee4a55c = _TYPEID_LSP7_TOKENSRECIPIENT
|
|
167
|
+
expect(wrapper?.args?.[2]?.value).toBe(
|
|
161
168
|
'0x20804611b3e2ea21c480dc465142210acf4a2485947541770ec1fb87dee4a55c'
|
|
162
169
|
)
|
|
163
170
|
|
|
164
|
-
// Verify the 'from' address in
|
|
165
|
-
expect(
|
|
171
|
+
// Verify the 'from' address in the wrapper (the minter, which is the UP)
|
|
172
|
+
expect(wrapper?.args?.[0]?.value).toBe(
|
|
166
173
|
'0x81A904879F657142d9b5C7e875c786717e2125c0'
|
|
167
174
|
)
|
|
168
175
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { universalProfileAbi as UniversalProfile } from '@lukso/universalprofile-contracts/abi'
|
|
2
|
-
import type { Address } from 'viem'
|
|
2
|
+
import type { Address, Hex, Log } from 'viem'
|
|
3
3
|
import { decodeEvent } from '../events'
|
|
4
4
|
import { decodeTransaction } from '../transaction'
|
|
5
5
|
import type {
|
|
@@ -15,6 +15,7 @@ import type {
|
|
|
15
15
|
import { createNamedArgs } from '../utils'
|
|
16
16
|
import { standardPlugin } from '.'
|
|
17
17
|
import { enhanceSetData } from './enhanceSetData'
|
|
18
|
+
import { unwrapUniversalReceiver } from './universalReceiverTypeIds'
|
|
18
19
|
|
|
19
20
|
export const enhanceLSP0ERC725AccountPlugin = standardPlugin(
|
|
20
21
|
UniversalProfile,
|
|
@@ -26,7 +27,43 @@ export const enhanceLSP0ERC725AccountPlugin = standardPlugin(
|
|
|
26
27
|
{
|
|
27
28
|
enhance: enhanceLSP0ERC725Account,
|
|
28
29
|
decodeEvent: async (log: DecodeEventResult, options: DecoderOptions) => {
|
|
29
|
-
|
|
30
|
+
const decoded = decodeEvent(options.chain, UniversalProfile, log)
|
|
31
|
+
if (!decoded || decoded.eventName !== 'UniversalReceiver') {
|
|
32
|
+
return decoded
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Extract UniversalReceiver args
|
|
36
|
+
const typeId = decoded.args.find((a) => a.name === 'typeId')?.value as Hex
|
|
37
|
+
const receivedData = decoded.args.find((a) => a.name === 'receivedData')
|
|
38
|
+
?.value as Hex
|
|
39
|
+
const from = decoded.args.find((a) => a.name === 'from')?.value as Address
|
|
40
|
+
const profileAddress = (decoded as unknown as Log).address as Address
|
|
41
|
+
|
|
42
|
+
if (!typeId || !receivedData || !from) {
|
|
43
|
+
return decoded
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Unwrap based on typeId (always succeeds — falls back to generic Notification)
|
|
47
|
+
const unwrapped = unwrapUniversalReceiver(
|
|
48
|
+
typeId,
|
|
49
|
+
receivedData,
|
|
50
|
+
from,
|
|
51
|
+
profileAddress
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
// Rewrite the event: inner event becomes the main event,
|
|
55
|
+
// original UniversalReceiver goes into wrappers.
|
|
56
|
+
// Topics and data are rewritten to match the inner event's ABI.
|
|
57
|
+
const { wrappers: _w, standard: _s, ...logBase } = decoded
|
|
58
|
+
return {
|
|
59
|
+
...logBase,
|
|
60
|
+
eventName: unwrapped.eventName,
|
|
61
|
+
args: unwrapped.args,
|
|
62
|
+
standard: unwrapped.standard,
|
|
63
|
+
topics: unwrapped.topics,
|
|
64
|
+
data: unwrapped.data,
|
|
65
|
+
wrappers: [logBase],
|
|
66
|
+
} as DecodeEventResult
|
|
30
67
|
},
|
|
31
68
|
}
|
|
32
69
|
)
|