@lukso/transaction-decoder 1.0.1-dev.0f1bea5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +486 -0
- package/dist/browser.cjs +6912 -0
- package/dist/browser.cjs.map +1 -0
- package/dist/browser.d.cts +6 -0
- package/dist/browser.d.ts +6 -0
- package/dist/browser.js +131 -0
- package/dist/browser.js.map +1 -0
- package/dist/cdn/transaction-decoder.global.js +296 -0
- package/dist/cdn/transaction-decoder.global.js.map +1 -0
- package/dist/chunk-GGBHTWJL.js +437 -0
- package/dist/chunk-GGBHTWJL.js.map +1 -0
- package/dist/chunk-GXZOF3QY.js +839 -0
- package/dist/chunk-GXZOF3QY.js.map +1 -0
- package/dist/chunk-LJ6ES5XF.js +776 -0
- package/dist/chunk-LJ6ES5XF.js.map +1 -0
- package/dist/chunk-XVHJWV5U.js +4925 -0
- package/dist/chunk-XVHJWV5U.js.map +1 -0
- package/dist/data.cjs +5518 -0
- package/dist/data.cjs.map +1 -0
- package/dist/data.d.cts +43 -0
- package/dist/data.d.ts +43 -0
- package/dist/data.js +55 -0
- package/dist/data.js.map +1 -0
- package/dist/index-BzXh7poJ.d.cts +524 -0
- package/dist/index-BzXh7poJ.d.ts +524 -0
- package/dist/index.cjs +6912 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +756 -0
- package/dist/index.d.ts +756 -0
- package/dist/index.js +131 -0
- package/dist/index.js.map +1 -0
- package/dist/server.cjs +5644 -0
- package/dist/server.cjs.map +1 -0
- package/dist/server.d.cts +217 -0
- package/dist/server.d.ts +217 -0
- package/dist/server.js +644 -0
- package/dist/server.js.map +1 -0
- package/dist/utils-CBAkjQh3.d.cts +108 -0
- package/dist/utils-xT9-km0r.d.ts +108 -0
- package/package.json +101 -0
- package/src/browser.ts +13 -0
- package/src/client/resolveAddresses.ts +157 -0
- package/src/core/addressCollector.ts +153 -0
- package/src/core/addressResolver.ts +135 -0
- package/src/core/dataModel.ts +888 -0
- package/src/core/instance.ts +33 -0
- package/src/core/integrateDecoder.ts +325 -0
- package/src/data.ts +70 -0
- package/src/decoder/GENERATOR_PROPOSAL.md +182 -0
- package/src/decoder/THREE_PHASE_EXAMPLE.md +108 -0
- package/src/decoder/aggregation.ts +218 -0
- package/src/decoder/browserCache.ts +237 -0
- package/src/decoder/cache/README.md +126 -0
- package/src/decoder/cache/index.ts +44 -0
- package/src/decoder/cache.ts +139 -0
- package/src/decoder/constants.ts +125 -0
- package/src/decoder/decodeTransaction.ts +292 -0
- package/src/decoder/errors.ts +95 -0
- package/src/decoder/events.ts +192 -0
- package/src/decoder/functionSignature.ts +344 -0
- package/src/decoder/getDataFromExternalSources.ts +248 -0
- package/src/decoder/graphqlWS.ts +22 -0
- package/src/decoder/interfaces.ts +185 -0
- package/src/decoder/keyValue.ts +5 -0
- package/src/decoder/kvCache.ts +241 -0
- package/src/decoder/lruCache.ts +184 -0
- package/src/decoder/lsp7Mint.test.ts +179 -0
- package/src/decoder/lsp7TransferBatch.test.ts +105 -0
- package/src/decoder/plugins/RegistryAbi.ts +562 -0
- package/src/decoder/plugins/enhanceBurntPix.ts +132 -0
- package/src/decoder/plugins/enhanceGraffiti.ts +70 -0
- package/src/decoder/plugins/enhanceLSP0ERC725Account.ts +179 -0
- package/src/decoder/plugins/enhanceLSP26FollowerSystem.ts +88 -0
- package/src/decoder/plugins/enhanceLSP6KeyManager.ts +231 -0
- package/src/decoder/plugins/enhanceLSP7DigitalAsset.ts +165 -0
- package/src/decoder/plugins/enhanceLSP8IdentifiableDigitalAsset.ts +170 -0
- package/src/decoder/plugins/enhanceLSP9Vault.ts +57 -0
- package/src/decoder/plugins/enhanceRetrieveAbi.ts +85 -0
- package/src/decoder/plugins/enhanceSetData.ts +135 -0
- package/src/decoder/plugins/index.ts +99 -0
- package/src/decoder/plugins/schemaDefault.ts +318 -0
- package/src/decoder/plugins/standardPlugin.ts +202 -0
- package/src/decoder/registry.ts +322 -0
- package/src/decoder/singleGQL.ts +293 -0
- package/src/decoder/transaction.ts +198 -0
- package/src/decoder/types.ts +465 -0
- package/src/decoder/utils.ts +212 -0
- package/src/example/usage.ts +172 -0
- package/src/index.ts +174 -0
- package/src/server/addressResolver.ts +68 -0
- package/src/server/caches.ts +209 -0
- package/src/server/decodeTransactionSync.ts +156 -0
- package/src/server/decodeTransactionsBatch.ts +207 -0
- package/src/server/finishDecoding.ts +116 -0
- package/src/server/index.ts +81 -0
- package/src/server/lsp23Resolver.test.ts +46 -0
- package/src/server/lsp23Resolver.ts +419 -0
- package/src/server/types.ts +168 -0
- package/src/server.ts +22 -0
- package/src/shared/addressResolver.ts +651 -0
- package/src/shared/cache.ts +144 -0
- package/src/shared/constants.ts +21 -0
- package/src/stubs/tty.ts +13 -0
- package/src/stubs/util.ts +42 -0
- package/src/types/index.ts +154 -0
- package/src/types/provider.ts +46 -0
- package/src/umd.ts +13 -0
- package/src/utils/debug.ts +49 -0
- package/src/utils/json-bigint.ts +47 -0
package/dist/server.js
ADDED
|
@@ -0,0 +1,644 @@
|
|
|
1
|
+
import {
|
|
2
|
+
fetchMultipleAddresses
|
|
3
|
+
} from "./chunk-GGBHTWJL.js";
|
|
4
|
+
import {
|
|
5
|
+
__name,
|
|
6
|
+
collectDataKeys,
|
|
7
|
+
createDebug,
|
|
8
|
+
decodeTransaction,
|
|
9
|
+
needsEnhancement,
|
|
10
|
+
pluginRegistry
|
|
11
|
+
} from "./chunk-XVHJWV5U.js";
|
|
12
|
+
|
|
13
|
+
// src/server/addressResolver.ts
|
|
14
|
+
var ServerAddressResolver = class {
|
|
15
|
+
constructor(graphqlEndpoint, chain, caches) {
|
|
16
|
+
this.graphqlEndpoint = graphqlEndpoint;
|
|
17
|
+
this.chain = chain;
|
|
18
|
+
this.caches = caches;
|
|
19
|
+
this.cacheAdapter = {
|
|
20
|
+
get: /* @__PURE__ */ __name((key) => this.caches.getAddress(key), "get"),
|
|
21
|
+
set: /* @__PURE__ */ __name((key, value) => this.caches.setAddress(key, value), "set"),
|
|
22
|
+
has: /* @__PURE__ */ __name((key) => this.caches.hasAddress(key), "has"),
|
|
23
|
+
getMany: /* @__PURE__ */ __name((keys) => this.caches.getAddresses(keys), "getMany")
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
static {
|
|
27
|
+
__name(this, "ServerAddressResolver");
|
|
28
|
+
}
|
|
29
|
+
cacheAdapter;
|
|
30
|
+
/**
|
|
31
|
+
* Resolve addresses, using cache when possible
|
|
32
|
+
*/
|
|
33
|
+
async resolveAddresses(addresses) {
|
|
34
|
+
return fetchMultipleAddresses(
|
|
35
|
+
addresses,
|
|
36
|
+
this.graphqlEndpoint,
|
|
37
|
+
this.cacheAdapter
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Resolve addresses with timeout
|
|
42
|
+
*/
|
|
43
|
+
async resolveAddressesWithTimeout(addresses, timeoutMs) {
|
|
44
|
+
return Promise.race([
|
|
45
|
+
this.resolveAddresses(addresses),
|
|
46
|
+
new Promise((resolve) => {
|
|
47
|
+
setTimeout(() => {
|
|
48
|
+
const results = this.caches.getAddresses(addresses);
|
|
49
|
+
resolve(results);
|
|
50
|
+
}, timeoutMs);
|
|
51
|
+
})
|
|
52
|
+
]);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Warm the cache with specific addresses
|
|
56
|
+
*/
|
|
57
|
+
async warmCache(addresses) {
|
|
58
|
+
await this.resolveAddresses(addresses);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
// src/server/caches.ts
|
|
63
|
+
import { LRUCache } from "lru-cache";
|
|
64
|
+
var ServerDecoderCaches = class {
|
|
65
|
+
static {
|
|
66
|
+
__name(this, "ServerDecoderCaches");
|
|
67
|
+
}
|
|
68
|
+
// Level 1: Decoded transaction cache (keyed by transaction hash)
|
|
69
|
+
transactionCache;
|
|
70
|
+
transactionStats = { hits: 0, misses: 0 };
|
|
71
|
+
// Level 2: Address metadata cache (keyed by address or address:tokenId)
|
|
72
|
+
addressCache;
|
|
73
|
+
addressStats = { hits: 0, misses: 0 };
|
|
74
|
+
// Level 3: Contract ABI cache (keyed by address)
|
|
75
|
+
abiCache;
|
|
76
|
+
abiStats = { hits: 0, misses: 0 };
|
|
77
|
+
// Level 4: Schema decode cache (keyed by key:value)
|
|
78
|
+
schemaCache;
|
|
79
|
+
schemaStats = { hits: 0, misses: 0 };
|
|
80
|
+
constructor(options = {}) {
|
|
81
|
+
this.transactionCache = new LRUCache({
|
|
82
|
+
max: options.transactionCacheSize || 1e4,
|
|
83
|
+
ttl: 1e3 * 60 * 60,
|
|
84
|
+
// 1 hour TTL
|
|
85
|
+
updateAgeOnGet: true,
|
|
86
|
+
updateAgeOnHas: true
|
|
87
|
+
});
|
|
88
|
+
this.addressCache = new LRUCache({
|
|
89
|
+
max: options.addressCacheSize || 5e4,
|
|
90
|
+
ttl: 1e3 * 60 * 60 * 24,
|
|
91
|
+
// 24 hour TTL
|
|
92
|
+
updateAgeOnGet: true,
|
|
93
|
+
updateAgeOnHas: true
|
|
94
|
+
});
|
|
95
|
+
this.abiCache = new LRUCache({
|
|
96
|
+
max: options.abiCacheSize || 5e3,
|
|
97
|
+
ttl: 1e3 * 60 * 60 * 24 * 7,
|
|
98
|
+
// 7 day TTL (ABIs rarely change)
|
|
99
|
+
updateAgeOnGet: true,
|
|
100
|
+
updateAgeOnHas: true
|
|
101
|
+
});
|
|
102
|
+
this.schemaCache = new LRUCache({
|
|
103
|
+
max: options.schemaCacheSize || 1e4,
|
|
104
|
+
ttl: 1e3 * 60 * 60,
|
|
105
|
+
// 1 hour TTL
|
|
106
|
+
updateAgeOnGet: true,
|
|
107
|
+
updateAgeOnHas: true
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Get cache key for a data key (address or address:tokenId)
|
|
112
|
+
*/
|
|
113
|
+
getDataKeyCacheKey(key) {
|
|
114
|
+
return key.toLowerCase();
|
|
115
|
+
}
|
|
116
|
+
// Transaction cache methods
|
|
117
|
+
getTransaction(hash) {
|
|
118
|
+
const result = this.transactionCache.get(hash.toLowerCase());
|
|
119
|
+
if (result) {
|
|
120
|
+
this.transactionStats.hits++;
|
|
121
|
+
return { ...result, cached: true };
|
|
122
|
+
}
|
|
123
|
+
this.transactionStats.misses++;
|
|
124
|
+
return void 0;
|
|
125
|
+
}
|
|
126
|
+
setTransaction(hash, result) {
|
|
127
|
+
this.transactionCache.set(hash.toLowerCase(), result);
|
|
128
|
+
}
|
|
129
|
+
// Address cache methods
|
|
130
|
+
getAddress(key) {
|
|
131
|
+
const cacheKey = this.getDataKeyCacheKey(key);
|
|
132
|
+
const result = this.addressCache.get(cacheKey);
|
|
133
|
+
if (result) {
|
|
134
|
+
this.addressStats.hits++;
|
|
135
|
+
return result;
|
|
136
|
+
}
|
|
137
|
+
this.addressStats.misses++;
|
|
138
|
+
return void 0;
|
|
139
|
+
}
|
|
140
|
+
setAddress(key, data) {
|
|
141
|
+
const cacheKey = this.getDataKeyCacheKey(key);
|
|
142
|
+
this.addressCache.set(cacheKey, data);
|
|
143
|
+
}
|
|
144
|
+
hasAddress(key) {
|
|
145
|
+
return this.addressCache.has(this.getDataKeyCacheKey(key));
|
|
146
|
+
}
|
|
147
|
+
getAddresses(keys) {
|
|
148
|
+
const results = /* @__PURE__ */ new Map();
|
|
149
|
+
for (const key of keys) {
|
|
150
|
+
const data = this.getAddress(key);
|
|
151
|
+
if (data) {
|
|
152
|
+
results.set(key, data);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return results;
|
|
156
|
+
}
|
|
157
|
+
// ABI cache methods
|
|
158
|
+
getAbi(address) {
|
|
159
|
+
const result = this.abiCache.get(address.toLowerCase());
|
|
160
|
+
if (result) {
|
|
161
|
+
this.abiStats.hits++;
|
|
162
|
+
return result;
|
|
163
|
+
}
|
|
164
|
+
this.abiStats.misses++;
|
|
165
|
+
return void 0;
|
|
166
|
+
}
|
|
167
|
+
setAbi(address, abi) {
|
|
168
|
+
this.abiCache.set(address.toLowerCase(), abi);
|
|
169
|
+
}
|
|
170
|
+
hasAbi(address) {
|
|
171
|
+
return this.abiCache.has(address.toLowerCase());
|
|
172
|
+
}
|
|
173
|
+
// Schema cache methods
|
|
174
|
+
getSchema(key, value) {
|
|
175
|
+
const cacheKey = `${key}:${value}`;
|
|
176
|
+
const result = this.schemaCache.get(cacheKey);
|
|
177
|
+
if (result) {
|
|
178
|
+
this.schemaStats.hits++;
|
|
179
|
+
return result;
|
|
180
|
+
}
|
|
181
|
+
this.schemaStats.misses++;
|
|
182
|
+
return void 0;
|
|
183
|
+
}
|
|
184
|
+
setSchema(key, value, info) {
|
|
185
|
+
const cacheKey = `${key}:${value}`;
|
|
186
|
+
this.schemaCache.set(cacheKey, info);
|
|
187
|
+
}
|
|
188
|
+
// Cache management
|
|
189
|
+
clear() {
|
|
190
|
+
this.transactionCache.clear();
|
|
191
|
+
this.addressCache.clear();
|
|
192
|
+
this.abiCache.clear();
|
|
193
|
+
this.schemaCache.clear();
|
|
194
|
+
this.transactionStats = { hits: 0, misses: 0 };
|
|
195
|
+
this.addressStats = { hits: 0, misses: 0 };
|
|
196
|
+
this.abiStats = { hits: 0, misses: 0 };
|
|
197
|
+
this.schemaStats = { hits: 0, misses: 0 };
|
|
198
|
+
}
|
|
199
|
+
getStats() {
|
|
200
|
+
const calculateHitRate = /* @__PURE__ */ __name((stats) => {
|
|
201
|
+
const total = stats.hits + stats.misses;
|
|
202
|
+
return total > 0 ? stats.hits / total : 0;
|
|
203
|
+
}, "calculateHitRate");
|
|
204
|
+
return {
|
|
205
|
+
transactions: {
|
|
206
|
+
size: this.transactionCache.size,
|
|
207
|
+
maxSize: this.transactionCache.max,
|
|
208
|
+
hits: this.transactionStats.hits,
|
|
209
|
+
misses: this.transactionStats.misses,
|
|
210
|
+
hitRate: calculateHitRate(this.transactionStats)
|
|
211
|
+
},
|
|
212
|
+
addresses: {
|
|
213
|
+
size: this.addressCache.size,
|
|
214
|
+
maxSize: this.addressCache.max,
|
|
215
|
+
hits: this.addressStats.hits,
|
|
216
|
+
misses: this.addressStats.misses,
|
|
217
|
+
hitRate: calculateHitRate(this.addressStats)
|
|
218
|
+
},
|
|
219
|
+
abis: {
|
|
220
|
+
size: this.abiCache.size,
|
|
221
|
+
maxSize: this.abiCache.max,
|
|
222
|
+
hits: this.abiStats.hits,
|
|
223
|
+
misses: this.abiStats.misses,
|
|
224
|
+
hitRate: calculateHitRate(this.abiStats)
|
|
225
|
+
},
|
|
226
|
+
schemas: {
|
|
227
|
+
size: this.schemaCache.size,
|
|
228
|
+
maxSize: this.schemaCache.max,
|
|
229
|
+
hits: this.schemaStats.hits,
|
|
230
|
+
misses: this.schemaStats.misses,
|
|
231
|
+
hitRate: calculateHitRate(this.schemaStats)
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
// src/server/decodeTransactionSync.ts
|
|
238
|
+
async function decodeTransactionSync(transaction, options, caches) {
|
|
239
|
+
const startTime = Date.now();
|
|
240
|
+
const { timeoutMs = 800, enableEnhancement = true, chain } = options;
|
|
241
|
+
if (transaction.hash) {
|
|
242
|
+
const cached = caches.getTransaction(transaction.hash);
|
|
243
|
+
if (cached) {
|
|
244
|
+
return cached;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
try {
|
|
248
|
+
const phase1Start = Date.now();
|
|
249
|
+
const plugins = await pluginRegistry.getAll({ syncOnly: true });
|
|
250
|
+
const schemaPlugins = pluginRegistry.getAllSchema();
|
|
251
|
+
const immediateOptions = {
|
|
252
|
+
chain,
|
|
253
|
+
plugins,
|
|
254
|
+
schemaPlugins,
|
|
255
|
+
wrappers: [],
|
|
256
|
+
async: false
|
|
257
|
+
};
|
|
258
|
+
const immediateResult = await decodeTransaction(
|
|
259
|
+
transaction,
|
|
260
|
+
immediateOptions
|
|
261
|
+
);
|
|
262
|
+
if (!immediateResult) {
|
|
263
|
+
return {
|
|
264
|
+
...createErrorResult(transaction),
|
|
265
|
+
phase: "immediate",
|
|
266
|
+
cached: false,
|
|
267
|
+
timeTaken: Date.now() - startTime
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
let currentResult = immediateResult;
|
|
271
|
+
let phase = "immediate";
|
|
272
|
+
if (immediateOptions.wrappers.length > 0) {
|
|
273
|
+
;
|
|
274
|
+
currentResult.wrappers = immediateOptions.wrappers;
|
|
275
|
+
}
|
|
276
|
+
const addresses = collectDataKeys(currentResult);
|
|
277
|
+
currentResult.addresses = addresses;
|
|
278
|
+
const phase1Time = Date.now() - phase1Start;
|
|
279
|
+
if (enableEnhancement && phase1Time < timeoutMs * 0.6) {
|
|
280
|
+
if (!needsEnhancement(currentResult)) {
|
|
281
|
+
phase = "enhanced";
|
|
282
|
+
} else {
|
|
283
|
+
try {
|
|
284
|
+
const allPlugins = await pluginRegistry.getAll();
|
|
285
|
+
const enhancedOptions = {
|
|
286
|
+
chain,
|
|
287
|
+
plugins: allPlugins,
|
|
288
|
+
schemaPlugins,
|
|
289
|
+
wrappers: [],
|
|
290
|
+
async: true
|
|
291
|
+
};
|
|
292
|
+
const enhancedResult = await Promise.race([
|
|
293
|
+
decodeTransaction(transaction, enhancedOptions),
|
|
294
|
+
// Timeout for phase 2
|
|
295
|
+
new Promise(
|
|
296
|
+
(resolve) => setTimeout(() => resolve(null), timeoutMs * 0.6 - phase1Time)
|
|
297
|
+
)
|
|
298
|
+
]);
|
|
299
|
+
if (enhancedResult) {
|
|
300
|
+
currentResult = enhancedResult;
|
|
301
|
+
phase = "enhanced";
|
|
302
|
+
const allWrappers = [
|
|
303
|
+
...immediateOptions.wrappers || [],
|
|
304
|
+
...enhancedOptions.wrappers || []
|
|
305
|
+
].filter(
|
|
306
|
+
(w, i, arr) => (
|
|
307
|
+
// Deduplicate by checking if this is the first occurrence
|
|
308
|
+
arr.findIndex(
|
|
309
|
+
(x) => JSON.stringify(x) === JSON.stringify(w)
|
|
310
|
+
) === i
|
|
311
|
+
)
|
|
312
|
+
);
|
|
313
|
+
if (allWrappers.length > 0) {
|
|
314
|
+
;
|
|
315
|
+
currentResult.wrappers = allWrappers;
|
|
316
|
+
}
|
|
317
|
+
currentResult.addresses = collectDataKeys(currentResult);
|
|
318
|
+
}
|
|
319
|
+
} catch (error) {
|
|
320
|
+
console.error("Enhancement failed:", error);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
const result = {
|
|
325
|
+
...currentResult,
|
|
326
|
+
phase,
|
|
327
|
+
cached: false,
|
|
328
|
+
timeTaken: Date.now() - startTime
|
|
329
|
+
};
|
|
330
|
+
if (transaction.hash) {
|
|
331
|
+
caches.setTransaction(transaction.hash, result);
|
|
332
|
+
}
|
|
333
|
+
return result;
|
|
334
|
+
} catch (error) {
|
|
335
|
+
console.error("Failed to decode transaction:", error);
|
|
336
|
+
return {
|
|
337
|
+
...createErrorResult(transaction),
|
|
338
|
+
phase: "immediate",
|
|
339
|
+
cached: false,
|
|
340
|
+
timeTaken: Date.now() - startTime
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
__name(decodeTransactionSync, "decodeTransactionSync");
|
|
345
|
+
function createErrorResult(transaction) {
|
|
346
|
+
return {
|
|
347
|
+
...transaction,
|
|
348
|
+
isDecoded: false,
|
|
349
|
+
resultType: "error",
|
|
350
|
+
errorType: "UNKNOWN",
|
|
351
|
+
sig: "0x",
|
|
352
|
+
addresses: []
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
__name(createErrorResult, "createErrorResult");
|
|
356
|
+
|
|
357
|
+
// src/server/decodeTransactionsBatch.ts
|
|
358
|
+
async function decodeTransactionsBatch(transactions, options, caches) {
|
|
359
|
+
const startTime = Date.now();
|
|
360
|
+
const { timeoutMs = 800, enableEnhancement = true, chain } = options;
|
|
361
|
+
const results = transactions.map((tx) => {
|
|
362
|
+
if (tx.transactionHash) {
|
|
363
|
+
const cached = caches.getTransaction(tx.transactionHash);
|
|
364
|
+
if (cached) return cached;
|
|
365
|
+
}
|
|
366
|
+
return null;
|
|
367
|
+
});
|
|
368
|
+
const uncachedIndexes = [];
|
|
369
|
+
const uncachedTransactions = [];
|
|
370
|
+
results.forEach((result, index) => {
|
|
371
|
+
if (!result) {
|
|
372
|
+
uncachedIndexes.push(index);
|
|
373
|
+
uncachedTransactions.push(transactions[index]);
|
|
374
|
+
}
|
|
375
|
+
});
|
|
376
|
+
if (uncachedTransactions.length === 0) {
|
|
377
|
+
return {
|
|
378
|
+
results
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
try {
|
|
382
|
+
const syncPlugins = await pluginRegistry.getAll({ syncOnly: true });
|
|
383
|
+
const allPlugins = await pluginRegistry.getAll();
|
|
384
|
+
const schemaPlugins = pluginRegistry.getAllSchema();
|
|
385
|
+
const phase1Start = Date.now();
|
|
386
|
+
const immediateOptionsArray = uncachedTransactions.map(() => ({
|
|
387
|
+
chain,
|
|
388
|
+
plugins: syncPlugins,
|
|
389
|
+
schemaPlugins,
|
|
390
|
+
wrappers: [],
|
|
391
|
+
async: false
|
|
392
|
+
}));
|
|
393
|
+
const immediateResults = (await Promise.all(
|
|
394
|
+
uncachedTransactions.map(async (tx, i) => {
|
|
395
|
+
return await decodeTransaction(tx, immediateOptionsArray[i]);
|
|
396
|
+
})
|
|
397
|
+
)).filter(Boolean);
|
|
398
|
+
const newResults = immediateResults.map((result, i) => {
|
|
399
|
+
const data = result || createErrorResult2(uncachedTransactions[i]);
|
|
400
|
+
if (immediateOptionsArray[i].wrappers.length > 0) {
|
|
401
|
+
;
|
|
402
|
+
data.wrappers = immediateOptionsArray[i].wrappers;
|
|
403
|
+
}
|
|
404
|
+
data.addresses = collectDataKeys(data);
|
|
405
|
+
data.timeTaken = Date.now() - startTime;
|
|
406
|
+
return data;
|
|
407
|
+
}).filter(Boolean);
|
|
408
|
+
const phase1Time = Date.now() - phase1Start;
|
|
409
|
+
if (enableEnhancement && phase1Time < timeoutMs * 0.6) {
|
|
410
|
+
try {
|
|
411
|
+
const enhancedOptionsArray = uncachedTransactions.map(() => ({
|
|
412
|
+
chain,
|
|
413
|
+
plugins: allPlugins,
|
|
414
|
+
schemaPlugins,
|
|
415
|
+
wrappers: [],
|
|
416
|
+
async: true
|
|
417
|
+
}));
|
|
418
|
+
const enhancePromises = uncachedTransactions.map((tx, i) => {
|
|
419
|
+
if (!immediateResults[i]) return null;
|
|
420
|
+
if (!needsEnhancement(immediateResults[i])) {
|
|
421
|
+
return null;
|
|
422
|
+
}
|
|
423
|
+
return decodeTransaction(tx, enhancedOptionsArray[i]);
|
|
424
|
+
});
|
|
425
|
+
const remainingTime = timeoutMs * 0.6 - phase1Time;
|
|
426
|
+
const enhancedResults = await Promise.all(enhancePromises);
|
|
427
|
+
enhancedResults.forEach((enhanced, i) => {
|
|
428
|
+
if (enhanced) {
|
|
429
|
+
const immediateWrappers = immediateOptionsArray[i].wrappers || [];
|
|
430
|
+
const enhancedWrappers = enhancedOptionsArray[i].wrappers || [];
|
|
431
|
+
const allWrappers = [
|
|
432
|
+
...immediateWrappers,
|
|
433
|
+
...enhancedWrappers
|
|
434
|
+
].filter(
|
|
435
|
+
(w, idx, arr) => (
|
|
436
|
+
// Deduplicate by checking if this is the first occurrence
|
|
437
|
+
arr.findIndex(
|
|
438
|
+
(x) => JSON.stringify(x) === JSON.stringify(w)
|
|
439
|
+
) === idx
|
|
440
|
+
)
|
|
441
|
+
);
|
|
442
|
+
newResults[i] = enhanced;
|
|
443
|
+
if (allWrappers.length > 0) {
|
|
444
|
+
;
|
|
445
|
+
newResults[i].wrappers = allWrappers;
|
|
446
|
+
}
|
|
447
|
+
newResults[i].addresses = collectDataKeys(enhanced);
|
|
448
|
+
newResults[i].phase = "enhanced";
|
|
449
|
+
} else if (immediateResults[i] && !needsEnhancement(immediateResults[i])) {
|
|
450
|
+
newResults[i].phase = "enhanced";
|
|
451
|
+
}
|
|
452
|
+
});
|
|
453
|
+
} catch (error) {
|
|
454
|
+
console.error("Batch enhancement failed:", error);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
const totalTime = Date.now() - startTime;
|
|
458
|
+
newResults.forEach((result) => {
|
|
459
|
+
result.timeTaken = totalTime;
|
|
460
|
+
});
|
|
461
|
+
newResults.forEach((result, i) => {
|
|
462
|
+
const tx = uncachedTransactions[i];
|
|
463
|
+
if (tx.hash) {
|
|
464
|
+
caches.setTransaction(tx.hash, result);
|
|
465
|
+
}
|
|
466
|
+
});
|
|
467
|
+
uncachedIndexes.forEach((originalIndex, i) => {
|
|
468
|
+
results[originalIndex] = newResults[i];
|
|
469
|
+
});
|
|
470
|
+
return {
|
|
471
|
+
results
|
|
472
|
+
};
|
|
473
|
+
} catch (error) {
|
|
474
|
+
console.error("Batch decode failed:", error);
|
|
475
|
+
uncachedIndexes.forEach((originalIndex) => {
|
|
476
|
+
results[originalIndex] = {
|
|
477
|
+
...createErrorResult2(transactions[originalIndex]),
|
|
478
|
+
phase: "immediate",
|
|
479
|
+
cached: false,
|
|
480
|
+
timeTaken: Date.now() - startTime
|
|
481
|
+
};
|
|
482
|
+
});
|
|
483
|
+
return {
|
|
484
|
+
results
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
__name(decodeTransactionsBatch, "decodeTransactionsBatch");
|
|
489
|
+
function createErrorResult2(transaction) {
|
|
490
|
+
return {
|
|
491
|
+
...transaction,
|
|
492
|
+
isDecoded: false,
|
|
493
|
+
resultType: "error",
|
|
494
|
+
errorType: "UNKNOWN",
|
|
495
|
+
sig: "0x",
|
|
496
|
+
addresses: []
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
__name(createErrorResult2, "createErrorResult");
|
|
500
|
+
|
|
501
|
+
// src/server/finishDecoding.ts
|
|
502
|
+
var debug = createDebug("decoder:finishDecoding");
|
|
503
|
+
async function finishDecoding(transaction, options, caches) {
|
|
504
|
+
const startTime = Date.now();
|
|
505
|
+
const {
|
|
506
|
+
timeoutMs = 5e3,
|
|
507
|
+
// Give more time for finishing
|
|
508
|
+
chain
|
|
509
|
+
} = options;
|
|
510
|
+
try {
|
|
511
|
+
const txHash = transaction.hash || transaction.transactionHash;
|
|
512
|
+
if (txHash) {
|
|
513
|
+
const cached = caches.getTransaction(txHash);
|
|
514
|
+
if (cached && cached.enhancementAttempted) {
|
|
515
|
+
return {
|
|
516
|
+
...cached,
|
|
517
|
+
cached: true,
|
|
518
|
+
timeTaken: 0
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
const allPlugins = await pluginRegistry.getAll();
|
|
523
|
+
const schemaPlugins = pluginRegistry.getAllSchema();
|
|
524
|
+
const enhancedOptions = {
|
|
525
|
+
chain,
|
|
526
|
+
plugins: allPlugins,
|
|
527
|
+
schemaPlugins,
|
|
528
|
+
wrappers: [],
|
|
529
|
+
async: true
|
|
530
|
+
};
|
|
531
|
+
const {
|
|
532
|
+
wrappers,
|
|
533
|
+
children: _children,
|
|
534
|
+
addresses: _addresses,
|
|
535
|
+
...transactionWithoutWrappers
|
|
536
|
+
} = transaction;
|
|
537
|
+
const enhancedResult = await decodeTransaction(
|
|
538
|
+
transactionWithoutWrappers,
|
|
539
|
+
enhancedOptions
|
|
540
|
+
);
|
|
541
|
+
if (!enhancedResult) {
|
|
542
|
+
if (txHash) {
|
|
543
|
+
caches.setTransaction(txHash, {
|
|
544
|
+
...transaction,
|
|
545
|
+
enhancementAttempted: true
|
|
546
|
+
});
|
|
547
|
+
}
|
|
548
|
+
return transaction;
|
|
549
|
+
}
|
|
550
|
+
const result = {
|
|
551
|
+
...enhancedResult,
|
|
552
|
+
// Only add wrappers if there are any
|
|
553
|
+
...(wrappers?.length || 0) > 0 ? { wrappers } : {},
|
|
554
|
+
cached: false,
|
|
555
|
+
timeTaken: Date.now() - startTime,
|
|
556
|
+
enhancementAttempted: true
|
|
557
|
+
};
|
|
558
|
+
if (txHash) {
|
|
559
|
+
caches.setTransaction(txHash, result);
|
|
560
|
+
}
|
|
561
|
+
return result;
|
|
562
|
+
} catch (error) {
|
|
563
|
+
console.error("Failed to finish decoding transaction:", error);
|
|
564
|
+
return {
|
|
565
|
+
...createErrorResult3(transaction),
|
|
566
|
+
phase: "immediate",
|
|
567
|
+
cached: false,
|
|
568
|
+
timeTaken: Date.now() - startTime
|
|
569
|
+
};
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
__name(finishDecoding, "finishDecoding");
|
|
573
|
+
function createErrorResult3(transaction) {
|
|
574
|
+
return {
|
|
575
|
+
...transaction,
|
|
576
|
+
resultType: "error",
|
|
577
|
+
errorType: "UNKNOWN",
|
|
578
|
+
sig: "0x",
|
|
579
|
+
addresses: []
|
|
580
|
+
};
|
|
581
|
+
}
|
|
582
|
+
__name(createErrorResult3, "createErrorResult");
|
|
583
|
+
|
|
584
|
+
// src/server/index.ts
|
|
585
|
+
function createServerDecoder(config) {
|
|
586
|
+
const caches = new ServerDecoderCaches({
|
|
587
|
+
transactionCacheSize: config.transactionCacheSize,
|
|
588
|
+
addressCacheSize: config.addressCacheSize,
|
|
589
|
+
abiCacheSize: config.abiCacheSize,
|
|
590
|
+
schemaCacheSize: config.schemaCacheSize
|
|
591
|
+
});
|
|
592
|
+
const addressResolver = new ServerAddressResolver(
|
|
593
|
+
config.graphqlEndpoint,
|
|
594
|
+
config.defaultChain,
|
|
595
|
+
caches
|
|
596
|
+
);
|
|
597
|
+
return {
|
|
598
|
+
async decodeTransaction(transaction, options) {
|
|
599
|
+
const opts = {
|
|
600
|
+
chain: config.defaultChain,
|
|
601
|
+
timeoutMs: config.defaultTimeout,
|
|
602
|
+
...options
|
|
603
|
+
};
|
|
604
|
+
return decodeTransactionSync(transaction, opts, caches);
|
|
605
|
+
},
|
|
606
|
+
async decodeTransactionsBatch(transactions, options) {
|
|
607
|
+
const opts = {
|
|
608
|
+
chain: config.defaultChain,
|
|
609
|
+
timeoutMs: config.defaultTimeout,
|
|
610
|
+
...options
|
|
611
|
+
};
|
|
612
|
+
return decodeTransactionsBatch(transactions, opts, caches);
|
|
613
|
+
},
|
|
614
|
+
async finishDecoding(transaction, options) {
|
|
615
|
+
const opts = {
|
|
616
|
+
chain: config.defaultChain,
|
|
617
|
+
timeoutMs: config.defaultTimeout,
|
|
618
|
+
...options
|
|
619
|
+
};
|
|
620
|
+
return finishDecoding(transaction, opts, caches);
|
|
621
|
+
},
|
|
622
|
+
clearCaches() {
|
|
623
|
+
caches.clear();
|
|
624
|
+
},
|
|
625
|
+
getCacheStats() {
|
|
626
|
+
return caches.getStats();
|
|
627
|
+
},
|
|
628
|
+
async warmAddressCache(addresses) {
|
|
629
|
+
await addressResolver.warmCache(addresses);
|
|
630
|
+
},
|
|
631
|
+
async resolveAddresses(addresses, timeoutMs = 3e3) {
|
|
632
|
+
return addressResolver.resolveAddressesWithTimeout(addresses, timeoutMs);
|
|
633
|
+
}
|
|
634
|
+
};
|
|
635
|
+
}
|
|
636
|
+
__name(createServerDecoder, "createServerDecoder");
|
|
637
|
+
export {
|
|
638
|
+
ServerAddressResolver,
|
|
639
|
+
ServerDecoderCaches,
|
|
640
|
+
createServerDecoder,
|
|
641
|
+
decodeTransactionSync,
|
|
642
|
+
decodeTransactionsBatch
|
|
643
|
+
};
|
|
644
|
+
//# sourceMappingURL=server.js.map
|