@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
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type Abi,
|
|
3
|
+
type AbiFunction,
|
|
4
|
+
AbiFunctionSignatureNotFoundError,
|
|
5
|
+
type AbiParameter,
|
|
6
|
+
type Address,
|
|
7
|
+
type Chain,
|
|
8
|
+
createPublicClient,
|
|
9
|
+
type DecodeFunctionDataParameters,
|
|
10
|
+
decodeAbiParameters,
|
|
11
|
+
Hex,
|
|
12
|
+
http,
|
|
13
|
+
type PublicClient,
|
|
14
|
+
slice,
|
|
15
|
+
toFunctionSelector,
|
|
16
|
+
} from 'viem'
|
|
17
|
+
import { formatAbiItem } from 'viem/utils'
|
|
18
|
+
import type {
|
|
19
|
+
ArrayArgs,
|
|
20
|
+
AsyncOperations,
|
|
21
|
+
CustomDecodeFunctionDataReturn,
|
|
22
|
+
DecoderResult,
|
|
23
|
+
EnhancedInfo,
|
|
24
|
+
} from './types'
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Custom decoder for function data with additional named args support
|
|
28
|
+
* It's essentially the same code as decodeFunctionData, but also
|
|
29
|
+
* returning a namedArgs where we zip together the args and the inputs.
|
|
30
|
+
*/
|
|
31
|
+
export function customDecodeFunctionData<
|
|
32
|
+
const abi extends Abi | readonly unknown[],
|
|
33
|
+
preferError = false,
|
|
34
|
+
>(
|
|
35
|
+
parameters: Partial<
|
|
36
|
+
DecodeFunctionDataParameters<abi> & {
|
|
37
|
+
namedArgs?:
|
|
38
|
+
| Record<number, AbiParameter & { value?: unknown }>
|
|
39
|
+
| Record<string, unknown>
|
|
40
|
+
}
|
|
41
|
+
>,
|
|
42
|
+
preferError?: boolean
|
|
43
|
+
) {
|
|
44
|
+
try {
|
|
45
|
+
const { abi, data } = parameters as DecodeFunctionDataParameters
|
|
46
|
+
const signature = slice(data, 0, 4)
|
|
47
|
+
const description: AbiFunction | undefined = (abi.find(
|
|
48
|
+
(x) =>
|
|
49
|
+
x.type === (preferError ? 'error' : 'function') &&
|
|
50
|
+
signature === toFunctionSelector(formatAbiItem(x))
|
|
51
|
+
) || undefined) as AbiFunction | undefined
|
|
52
|
+
if (!description)
|
|
53
|
+
throw new AbiFunctionSignatureNotFoundError(signature, {
|
|
54
|
+
docsPath: '/docs/contract/decodeFunctionData',
|
|
55
|
+
})
|
|
56
|
+
const args = (
|
|
57
|
+
'inputs' in description &&
|
|
58
|
+
description.inputs &&
|
|
59
|
+
description.inputs.length > 0
|
|
60
|
+
? decodeAbiParameters(description.inputs, slice(data, 4))
|
|
61
|
+
: undefined
|
|
62
|
+
) as readonly unknown[] | undefined
|
|
63
|
+
const result: {
|
|
64
|
+
functionName: string
|
|
65
|
+
sig: Hex
|
|
66
|
+
input: Hex
|
|
67
|
+
args?: ArrayArgs
|
|
68
|
+
} = {
|
|
69
|
+
functionName: (description as { name: string }).name,
|
|
70
|
+
sig: signature,
|
|
71
|
+
input: data,
|
|
72
|
+
}
|
|
73
|
+
if (args) {
|
|
74
|
+
const { args: namedArgs } = createNamedArgs(args, description.inputs)
|
|
75
|
+
result.args = namedArgs
|
|
76
|
+
}
|
|
77
|
+
return result as CustomDecodeFunctionDataReturn<abi>
|
|
78
|
+
} catch {}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function createNamedArgs(
|
|
82
|
+
args: unknown[] | readonly unknown[],
|
|
83
|
+
inputs?: AbiParameter[] | readonly AbiParameter[]
|
|
84
|
+
): { args: ArrayArgs } {
|
|
85
|
+
const array = args.map((value, index) => {
|
|
86
|
+
return {
|
|
87
|
+
name: `args${index + 1}`,
|
|
88
|
+
...inputs?.[index],
|
|
89
|
+
value,
|
|
90
|
+
} as AbiParameter & { value: unknown }
|
|
91
|
+
})
|
|
92
|
+
return { args: array }
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Get an argument value by its name from the args array.
|
|
97
|
+
* This utility function allows accessing arguments by name without needing namedArgs.
|
|
98
|
+
*
|
|
99
|
+
* @param args - The array of arguments with their metadata
|
|
100
|
+
* @param name - The name of the argument to find
|
|
101
|
+
* @returns The value of the argument if found, undefined otherwise
|
|
102
|
+
*/
|
|
103
|
+
export function getArgByName(
|
|
104
|
+
args: ArrayArgs | undefined,
|
|
105
|
+
name: string
|
|
106
|
+
): unknown {
|
|
107
|
+
if (!args) return undefined
|
|
108
|
+
|
|
109
|
+
const arg = args.find((arg) => arg.name === name)
|
|
110
|
+
return arg?.value
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export function extractAddress(address?: Address | EnhancedInfo) {
|
|
114
|
+
if (typeof address === 'object') {
|
|
115
|
+
return address.address
|
|
116
|
+
}
|
|
117
|
+
return address
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const clients: Record<number, PublicClient> = {} as Record<number, PublicClient>
|
|
121
|
+
export function getPublicClient(chain: Chain): PublicClient {
|
|
122
|
+
const { id } = chain
|
|
123
|
+
if (!id) {
|
|
124
|
+
throw new Error('Chain ID is required to create a public client')
|
|
125
|
+
}
|
|
126
|
+
if (!clients[id]) {
|
|
127
|
+
clients[id] = createPublicClient({
|
|
128
|
+
chain,
|
|
129
|
+
transport: http(),
|
|
130
|
+
batch: {
|
|
131
|
+
multicall: {
|
|
132
|
+
batchSize: 100,
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
})
|
|
136
|
+
}
|
|
137
|
+
const result = clients[id]
|
|
138
|
+
if (!result) {
|
|
139
|
+
throw new Error(`Public client for chain ID ${id} not found`)
|
|
140
|
+
}
|
|
141
|
+
return result
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Helper to check if a specific async operation is enabled
|
|
146
|
+
*/
|
|
147
|
+
export function isAsyncOperationEnabled(
|
|
148
|
+
asyncOption: boolean | AsyncOperations | undefined,
|
|
149
|
+
operation: AsyncOperations
|
|
150
|
+
): boolean {
|
|
151
|
+
// Handle backward compatibility
|
|
152
|
+
if (typeof asyncOption === 'boolean') {
|
|
153
|
+
return asyncOption
|
|
154
|
+
}
|
|
155
|
+
// If not specified, default to DISABLED
|
|
156
|
+
if (asyncOption === undefined) {
|
|
157
|
+
return false
|
|
158
|
+
}
|
|
159
|
+
// Check bitmap
|
|
160
|
+
return (asyncOption & operation) !== 0
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Check if a single decoded item needs enhancement
|
|
165
|
+
* @param item - A single decoded result (not checking children)
|
|
166
|
+
* @returns true if this specific item needs enhancement
|
|
167
|
+
*/
|
|
168
|
+
function needsEnhancementSingle(item: DecoderResult): boolean {
|
|
169
|
+
// If sig is "0x", there's no function signature to decode
|
|
170
|
+
if ('sig' in item && item.sig === '0x') {
|
|
171
|
+
return false
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// If it has a standard, it's already identified
|
|
175
|
+
if (item.standard) {
|
|
176
|
+
return false
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Otherwise it needs enhancement
|
|
180
|
+
return true
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Check if a decoded result needs enhancement
|
|
185
|
+
* Returns true if the result OR any of its children need enhancement
|
|
186
|
+
*/
|
|
187
|
+
export function needsEnhancement(result: DecoderResult): boolean {
|
|
188
|
+
// Check if the main result needs enhancement
|
|
189
|
+
if (needsEnhancementSingle(result)) {
|
|
190
|
+
return true
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Check if any children need enhancement
|
|
194
|
+
if ('children' in result && Array.isArray(result.children)) {
|
|
195
|
+
return result.children.some((child) => {
|
|
196
|
+
// Children might be ResultType or ResultSetData, which don't have all DecoderResult fields
|
|
197
|
+
// We only check for standard property which is common to all
|
|
198
|
+
if (child.standard) {
|
|
199
|
+
return false
|
|
200
|
+
}
|
|
201
|
+
// If sig is "0x", there's no function signature to decode
|
|
202
|
+
if ('sig' in child && child.sig === '0x') {
|
|
203
|
+
return false
|
|
204
|
+
}
|
|
205
|
+
// Otherwise it needs enhancement
|
|
206
|
+
return true
|
|
207
|
+
})
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Nothing needs enhancement
|
|
211
|
+
return false
|
|
212
|
+
}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import debug from 'debug'
|
|
2
|
+
import type { Transaction } from 'viem'
|
|
3
|
+
import { lukso } from 'viem/chains'
|
|
4
|
+
import { createDataModel } from '../data'
|
|
5
|
+
import {
|
|
6
|
+
AddressResolver,
|
|
7
|
+
createMemoryAddressCache,
|
|
8
|
+
DecoderIntegration,
|
|
9
|
+
DecoderResult,
|
|
10
|
+
} from '../index'
|
|
11
|
+
|
|
12
|
+
const setupDecoderLog = debug('app:setupDecoder')
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Example of how to connect all the decoder pieces together
|
|
16
|
+
*/
|
|
17
|
+
export async function setupDecoder() {
|
|
18
|
+
// 1. Create data model with callbacks
|
|
19
|
+
const dataModel = createDataModel({
|
|
20
|
+
onMissingKeys: (keys) => {
|
|
21
|
+
setupDecoderLog('Missing address data for:', keys)
|
|
22
|
+
// Could trigger address resolution here
|
|
23
|
+
},
|
|
24
|
+
onNewTransaction: (tx) => {
|
|
25
|
+
setupDecoderLog('New transaction added:', tx)
|
|
26
|
+
},
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
// 2. Create address cache (could be IndexedDB, localStorage, etc)
|
|
30
|
+
const addressCache = createMemoryAddressCache()
|
|
31
|
+
|
|
32
|
+
// Alternative: Create IndexedDB cache
|
|
33
|
+
// const addressCache = createIndexedDBCache('decoder-addresses')
|
|
34
|
+
|
|
35
|
+
// 3. Create decoder integration
|
|
36
|
+
const decoder = new DecoderIntegration({
|
|
37
|
+
dataModel,
|
|
38
|
+
decoderOptions: {
|
|
39
|
+
chain: lukso,
|
|
40
|
+
preferError: false,
|
|
41
|
+
},
|
|
42
|
+
addressCache,
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
// 4. Create address resolver for GraphQL
|
|
46
|
+
const addressResolver = new AddressResolver({
|
|
47
|
+
dataModel,
|
|
48
|
+
graphqlEndpoint: 'https://api.universalprofile.cloud/graphql',
|
|
49
|
+
chain: lukso,
|
|
50
|
+
batchSize: 50,
|
|
51
|
+
batchDelay: 100,
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
// 5. Start watching for missing addresses
|
|
55
|
+
addressResolver.startWatching()
|
|
56
|
+
|
|
57
|
+
return {
|
|
58
|
+
dataModel,
|
|
59
|
+
decoder,
|
|
60
|
+
addressResolver,
|
|
61
|
+
addressCache,
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Example of adding and decoding transactions
|
|
67
|
+
*/
|
|
68
|
+
export async function handleTransaction(tx: DecoderResult) {
|
|
69
|
+
const { decoder } = await setupDecoder()
|
|
70
|
+
|
|
71
|
+
// Add and decode transaction
|
|
72
|
+
const signal = await decoder.addAndDecodeTransaction(tx)
|
|
73
|
+
|
|
74
|
+
// React to updates
|
|
75
|
+
signal.subscribe((state) => {
|
|
76
|
+
setupDecoderLog('Transaction state updated:', {
|
|
77
|
+
loading: state.loading,
|
|
78
|
+
decodingStatus: state.decodingStatus,
|
|
79
|
+
addresses: state.addresses,
|
|
80
|
+
data: state.data,
|
|
81
|
+
})
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
// Get immediate data
|
|
85
|
+
const currentState = signal.value
|
|
86
|
+
setupDecoderLog('Current transaction data:', currentState.data)
|
|
87
|
+
|
|
88
|
+
return signal
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Example of batch processing
|
|
93
|
+
*/
|
|
94
|
+
export async function handleTransactionBatch(transactions: DecoderResult[]) {
|
|
95
|
+
const { decoder, dataModel } = await setupDecoder()
|
|
96
|
+
|
|
97
|
+
// Add and decode all transactions
|
|
98
|
+
const signals = await decoder.addAndDecodeTransactions(transactions)
|
|
99
|
+
|
|
100
|
+
// Monitor overall progress
|
|
101
|
+
let completed = 0
|
|
102
|
+
for (const signal of signals) {
|
|
103
|
+
signal.subscribe((state) => {
|
|
104
|
+
if (
|
|
105
|
+
state.decodingStatus === 'complete' ||
|
|
106
|
+
state.decodingStatus === 'failed'
|
|
107
|
+
) {
|
|
108
|
+
completed++
|
|
109
|
+
setupDecoderLog(`Progress: ${completed}/${transactions.length}`)
|
|
110
|
+
}
|
|
111
|
+
})
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Get all transaction data
|
|
115
|
+
const allTransactions = dataModel.getAllTransactions()
|
|
116
|
+
setupDecoderLog('All transactions:', allTransactions)
|
|
117
|
+
|
|
118
|
+
return signals
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Example of manual address resolution
|
|
123
|
+
*/
|
|
124
|
+
export async function resolveAddresses() {
|
|
125
|
+
const { dataModel, decoder } = await setupDecoder()
|
|
126
|
+
|
|
127
|
+
// Get missing addresses
|
|
128
|
+
const missing = decoder.getMissingAddresses()
|
|
129
|
+
setupDecoderLog('Missing addresses:', missing)
|
|
130
|
+
|
|
131
|
+
// Manually fetch and inject address data
|
|
132
|
+
// (normally handled by AddressResolver automatically)
|
|
133
|
+
const addressData = await fetchAddressDataFromAPI(missing)
|
|
134
|
+
await decoder.loadAddressData(addressData)
|
|
135
|
+
|
|
136
|
+
// Check if all resolved
|
|
137
|
+
const stillMissing = decoder.getMissingAddresses()
|
|
138
|
+
setupDecoderLog('Still missing:', stillMissing)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Mock function for example
|
|
142
|
+
async function fetchAddressDataFromAPI(addresses: unknown[]) {
|
|
143
|
+
// This would be your actual API call
|
|
144
|
+
return []
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Example of using with a UI framework (e.g., Vue)
|
|
149
|
+
*/
|
|
150
|
+
export function useInVueComponent() {
|
|
151
|
+
// In a Vue component
|
|
152
|
+
/*
|
|
153
|
+
import { computed, onMounted } from 'vue'
|
|
154
|
+
import { getAddress, getTransaction } from '@lukso/decoder'
|
|
155
|
+
|
|
156
|
+
export default {
|
|
157
|
+
props: ['address', 'txHash'],
|
|
158
|
+
setup(props) {
|
|
159
|
+
const addressSignal = getAddress(props.address)
|
|
160
|
+
const txSignal = getTransaction({ hash: props.txHash })
|
|
161
|
+
|
|
162
|
+
const addressName = computed(() => addressSignal.value.data?.name || 'Unknown')
|
|
163
|
+
const txStatus = computed(() => txSignal?.value.decodingStatus || 'loading')
|
|
164
|
+
|
|
165
|
+
return {
|
|
166
|
+
addressName,
|
|
167
|
+
txStatus
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
*/
|
|
172
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @lukso/decoder - Consumer API
|
|
3
|
+
*
|
|
4
|
+
* This is the main entry point for consumers of the decoder.
|
|
5
|
+
* Import data provider functions from '@lukso/transaction-decoder/data' instead.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { consumerModel, createGlobalInstance } from './core/instance'
|
|
9
|
+
|
|
10
|
+
// Export all types that consumers need
|
|
11
|
+
export type {
|
|
12
|
+
AddressState,
|
|
13
|
+
DataKey,
|
|
14
|
+
EnhancedInfo,
|
|
15
|
+
IDataModelConsumer,
|
|
16
|
+
TransactionState,
|
|
17
|
+
} from './types'
|
|
18
|
+
// DecoderResult is exported from decoder/types via the decoder imports below
|
|
19
|
+
|
|
20
|
+
// Export all consumer methods directly
|
|
21
|
+
export const getTransaction = consumerModel.getTransaction.bind(consumerModel)
|
|
22
|
+
export const getTransactionByKey =
|
|
23
|
+
consumerModel.getTransactionByKey.bind(consumerModel)
|
|
24
|
+
export const getTransactionsByIndex =
|
|
25
|
+
consumerModel.getTransactionsByIndex.bind(consumerModel)
|
|
26
|
+
export const getTransactionHashByIndex =
|
|
27
|
+
consumerModel.getTransactionHashByIndex.bind(consumerModel)
|
|
28
|
+
export const getTransactionCount =
|
|
29
|
+
consumerModel.getTransactionCount.bind(consumerModel)
|
|
30
|
+
export const getDecodedCount = consumerModel.getDecodedCount.bind(consumerModel)
|
|
31
|
+
export const getDecodedTransactions =
|
|
32
|
+
consumerModel.getDecodedTransactions.bind(consumerModel)
|
|
33
|
+
export const getTransactionsInOrder =
|
|
34
|
+
consumerModel.getTransactionsInOrder.bind(consumerModel)
|
|
35
|
+
|
|
36
|
+
// Address methods
|
|
37
|
+
export const getAddress = consumerModel.getAddress.bind(consumerModel)
|
|
38
|
+
export const getSignal = consumerModel.getSignal.bind(consumerModel)
|
|
39
|
+
export const subscribe = consumerModel.subscribe.bind(consumerModel)
|
|
40
|
+
export const getState = consumerModel.getState.bind(consumerModel)
|
|
41
|
+
export const hasData = consumerModel.hasData.bind(consumerModel)
|
|
42
|
+
export const getData = consumerModel.getData.bind(consumerModel)
|
|
43
|
+
export const isLoading = consumerModel.isLoading.bind(consumerModel)
|
|
44
|
+
export const getError = consumerModel.getError.bind(consumerModel)
|
|
45
|
+
|
|
46
|
+
// Collection methods
|
|
47
|
+
export const getAllKeys = consumerModel.getAllKeys.bind(consumerModel)
|
|
48
|
+
export const getAllData = consumerModel.getAllData.bind(consumerModel)
|
|
49
|
+
export const getAllTransactions =
|
|
50
|
+
consumerModel.getAllTransactions.bind(consumerModel)
|
|
51
|
+
|
|
52
|
+
// Also export the consumer model instance for advanced usage
|
|
53
|
+
export { consumerModel }
|
|
54
|
+
|
|
55
|
+
// Export the function to create global instance (for manual setup)
|
|
56
|
+
export { createGlobalInstance }
|
|
57
|
+
|
|
58
|
+
// Export client utilities
|
|
59
|
+
export {
|
|
60
|
+
createApiAddressResolver,
|
|
61
|
+
type ResolveAddressesOptions,
|
|
62
|
+
type ResolveAddressesResponse,
|
|
63
|
+
resolveAddresses,
|
|
64
|
+
} from './client/resolveAddresses'
|
|
65
|
+
// Export address collection utilities from core
|
|
66
|
+
export { collectDataKeys } from './core/addressCollector'
|
|
67
|
+
export {
|
|
68
|
+
AddressResolver,
|
|
69
|
+
type AddressResolverConfig,
|
|
70
|
+
} from './core/addressResolver'
|
|
71
|
+
// Export integration classes
|
|
72
|
+
export {
|
|
73
|
+
type AddressCache,
|
|
74
|
+
createMemoryAddressCache,
|
|
75
|
+
DecoderIntegration,
|
|
76
|
+
type DecoderIntegrationConfig,
|
|
77
|
+
} from './core/integrateDecoder'
|
|
78
|
+
// Export aggregation utilities
|
|
79
|
+
export {
|
|
80
|
+
type AggregationState,
|
|
81
|
+
PluginAggregationEngine,
|
|
82
|
+
standardAggregation,
|
|
83
|
+
} from './decoder/aggregation'
|
|
84
|
+
export type {
|
|
85
|
+
AddressResolver as TransactionAddressResolver,
|
|
86
|
+
TransactionDecoderResult,
|
|
87
|
+
} from './decoder/decodeTransaction'
|
|
88
|
+
// Export decoder integration utilities
|
|
89
|
+
export {
|
|
90
|
+
decodeTransaction,
|
|
91
|
+
decodeTransactionAsync,
|
|
92
|
+
} from './decoder/decodeTransaction'
|
|
93
|
+
// Export plugin development utilities
|
|
94
|
+
// Export default plugins to ensure they're imported and register themselves
|
|
95
|
+
export {
|
|
96
|
+
createAggregationKey,
|
|
97
|
+
defaultPlugins,
|
|
98
|
+
defaultSchemaPlugins,
|
|
99
|
+
standardPlugin,
|
|
100
|
+
standardSchemaPlugin,
|
|
101
|
+
} from './decoder/plugins'
|
|
102
|
+
export type {
|
|
103
|
+
PluginMetadata,
|
|
104
|
+
SchemaPluginMetadata,
|
|
105
|
+
} from './decoder/registry'
|
|
106
|
+
export {
|
|
107
|
+
createNamedPlugin,
|
|
108
|
+
createNamedSchemaPlugin,
|
|
109
|
+
pluginRegistry,
|
|
110
|
+
registerPlugin,
|
|
111
|
+
registerSchemaPlugin,
|
|
112
|
+
} from './decoder/registry'
|
|
113
|
+
export type {
|
|
114
|
+
Aggregation,
|
|
115
|
+
DecodeEventCallback,
|
|
116
|
+
DecodeEventResult,
|
|
117
|
+
DecoderPlugin,
|
|
118
|
+
DecoderResult,
|
|
119
|
+
EnhancerCallback,
|
|
120
|
+
PluginOptions,
|
|
121
|
+
ResultAggregate,
|
|
122
|
+
ResultCreate,
|
|
123
|
+
ResultError,
|
|
124
|
+
ResultExecute,
|
|
125
|
+
ResultExecuteBatch,
|
|
126
|
+
ResultFollowProfile,
|
|
127
|
+
ResultGrafitti,
|
|
128
|
+
ResultRaw,
|
|
129
|
+
ResultSetData,
|
|
130
|
+
ResultSetDataBatch,
|
|
131
|
+
ResultWrapper,
|
|
132
|
+
SchemaPlugin,
|
|
133
|
+
} from './decoder/types'
|
|
134
|
+
// Export utility functions
|
|
135
|
+
export { getArgByName, needsEnhancement } from './decoder/utils'
|
|
136
|
+
// Export LSP23 deployment resolver utilities
|
|
137
|
+
// Note: Actual Hypersync querying should be done via wallet-app API to protect HYPERSYNC_TOKEN
|
|
138
|
+
export {
|
|
139
|
+
buildLSP23DeploymentQuery,
|
|
140
|
+
DEPLOY_ERC1167_PROXIES_SELECTOR,
|
|
141
|
+
decodeDeploymentCalldata,
|
|
142
|
+
decodeDeploymentOutput,
|
|
143
|
+
extractControllersFromInitCalldata,
|
|
144
|
+
type HypersyncQueryConfig,
|
|
145
|
+
LSP23_FACTORY_ADDRESS,
|
|
146
|
+
type LSP23DeploymentData,
|
|
147
|
+
parseLSP23DeploymentsFromHypersync,
|
|
148
|
+
} from './server/lsp23Resolver'
|
|
149
|
+
// Export shared address resolver utilities
|
|
150
|
+
export {
|
|
151
|
+
type AssetData,
|
|
152
|
+
fetchMultipleAddresses,
|
|
153
|
+
fetchProfilesByControllers,
|
|
154
|
+
getGraphQLEndpoint,
|
|
155
|
+
getImage,
|
|
156
|
+
type ImageData,
|
|
157
|
+
type ImageURL,
|
|
158
|
+
type LinkData,
|
|
159
|
+
type ProfileData,
|
|
160
|
+
type TFetchAddressData,
|
|
161
|
+
type TokenData,
|
|
162
|
+
} from './shared/addressResolver'
|
|
163
|
+
// Export cache utilities
|
|
164
|
+
export {
|
|
165
|
+
type AddressIdentityCache,
|
|
166
|
+
createMemoryAddressIdentityCache,
|
|
167
|
+
dataKeyToString,
|
|
168
|
+
getDataKeyCacheKey,
|
|
169
|
+
parseDataKey,
|
|
170
|
+
} from './shared/cache'
|
|
171
|
+
// Export debug utility for edge/worker environments
|
|
172
|
+
export { createDebug } from './utils/debug'
|
|
173
|
+
// Export JSON BigInt serializer/deserializer
|
|
174
|
+
export { JSONbigString } from './utils/json-bigint'
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { Chain } from 'viem'
|
|
2
|
+
import { fetchMultipleAddresses } from '../shared/addressResolver'
|
|
3
|
+
import type { AddressIdentityCache } from '../shared/cache'
|
|
4
|
+
import type { DataKey, EnhancedInfo } from '../types'
|
|
5
|
+
import type { ServerDecoderCaches } from './caches'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Server-side address resolver with caching
|
|
9
|
+
*/
|
|
10
|
+
export class ServerAddressResolver {
|
|
11
|
+
private cacheAdapter: AddressIdentityCache
|
|
12
|
+
|
|
13
|
+
constructor(
|
|
14
|
+
private graphqlEndpoint: string,
|
|
15
|
+
private chain: Chain,
|
|
16
|
+
private caches: ServerDecoderCaches
|
|
17
|
+
) {
|
|
18
|
+
// Create adapter to use ServerDecoderCaches as AddressIdentityCache
|
|
19
|
+
this.cacheAdapter = {
|
|
20
|
+
get: (key: DataKey) => this.caches.getAddress(key),
|
|
21
|
+
set: (key: DataKey, value: EnhancedInfo) =>
|
|
22
|
+
this.caches.setAddress(key, value),
|
|
23
|
+
has: (key: DataKey) => this.caches.hasAddress(key),
|
|
24
|
+
getMany: (keys: DataKey[]) => this.caches.getAddresses(keys),
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Resolve addresses, using cache when possible
|
|
30
|
+
*/
|
|
31
|
+
async resolveAddresses(
|
|
32
|
+
addresses: readonly DataKey[]
|
|
33
|
+
): Promise<Map<DataKey, EnhancedInfo>> {
|
|
34
|
+
// Use the shared implementation with cache adapter
|
|
35
|
+
return fetchMultipleAddresses(
|
|
36
|
+
addresses,
|
|
37
|
+
this.graphqlEndpoint,
|
|
38
|
+
this.cacheAdapter
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Resolve addresses with timeout
|
|
44
|
+
*/
|
|
45
|
+
async resolveAddressesWithTimeout(
|
|
46
|
+
addresses: DataKey[],
|
|
47
|
+
timeoutMs: number
|
|
48
|
+
): Promise<Map<DataKey, EnhancedInfo>> {
|
|
49
|
+
return Promise.race([
|
|
50
|
+
this.resolveAddresses(addresses),
|
|
51
|
+
new Promise<Map<DataKey, EnhancedInfo>>((resolve) => {
|
|
52
|
+
setTimeout(() => {
|
|
53
|
+
// On timeout, return whatever we have cached
|
|
54
|
+
const results = this.caches.getAddresses(addresses)
|
|
55
|
+
resolve(results)
|
|
56
|
+
}, timeoutMs)
|
|
57
|
+
}),
|
|
58
|
+
])
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Warm the cache with specific addresses
|
|
63
|
+
*/
|
|
64
|
+
async warmCache(addresses: DataKey[]): Promise<void> {
|
|
65
|
+
// Simply call resolveAddresses which will cache any uncached addresses
|
|
66
|
+
await this.resolveAddresses(addresses)
|
|
67
|
+
}
|
|
68
|
+
}
|