@lukso/transaction-view-core 0.6.5-dev.14d5261 → 0.6.6-dev.2b7df2e
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/.turbo/turbo-build.log +10 -10
- package/.turbo/turbo-typecheck.log +1 -1
- package/CHANGELOG.md +15 -0
- package/dist/index.cjs +102 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +34 -16
- package/dist/index.d.ts +34 -16
- package/dist/index.js +105 -3
- package/dist/index.js.map +1 -1
- package/package.json +11 -6
- package/src/components/transaction-playback.ts +162 -19
- package/tsup.config.ts +3 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lukso/transaction-view-core",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.6-dev.2b7df2e",
|
|
4
4
|
"description": "Core components and hooks for LUKSO transaction display",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -30,18 +30,23 @@
|
|
|
30
30
|
}
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@
|
|
34
|
-
"@lukso/web-components": "^1.172.18",
|
|
33
|
+
"@lukso/web-components": "^1.172.20",
|
|
35
34
|
"@preact/signals-core": "^1.12.1",
|
|
36
35
|
"ethereum-blockies-base64": "^1.0.2",
|
|
37
|
-
"
|
|
38
|
-
"@lukso/transaction-
|
|
39
|
-
"@lukso/transaction-
|
|
36
|
+
"viem": "^2.43.5",
|
|
37
|
+
"@lukso/transaction-decoder": "1.3.6-dev.2b7df2e",
|
|
38
|
+
"@lukso/transaction-view-headless": "0.4.6-dev.2b7df2e"
|
|
39
|
+
},
|
|
40
|
+
"peerDependencies": {
|
|
41
|
+
"@lit/task": "^1.0.3",
|
|
42
|
+
"lit": "3.3.1"
|
|
40
43
|
},
|
|
41
44
|
"devDependencies": {
|
|
45
|
+
"@lit/task": "^1.0.3",
|
|
42
46
|
"@tailwindcss/typography": "^0.5.19",
|
|
43
47
|
"@types/postcss-import": "^14.0.3",
|
|
44
48
|
"autoprefixer": "^10.4.23",
|
|
49
|
+
"lit": "3.3.1",
|
|
45
50
|
"postcss": "^8.5.6",
|
|
46
51
|
"postcss-import": "^16.1.1",
|
|
47
52
|
"tailwindcss": "^3.4.19",
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {
|
|
2
|
+
type DecoderResult,
|
|
3
|
+
decodeTransaction,
|
|
4
|
+
JSONbigString,
|
|
5
|
+
} from '@lukso/transaction-decoder'
|
|
2
6
|
import {
|
|
3
7
|
createTransactionPlayback,
|
|
4
8
|
isHeaderInfoEvent,
|
|
@@ -13,15 +17,26 @@ import { html, type PropertyValues } from 'lit'
|
|
|
13
17
|
import { property, state } from 'lit/decorators.js'
|
|
14
18
|
import { createRef, type Ref, ref } from 'lit/directives/ref.js'
|
|
15
19
|
import { when } from 'lit/directives/when.js'
|
|
20
|
+
import type { Chain, Transaction } from 'viem'
|
|
16
21
|
import { getGlobalLitLoader } from '../registry/lit-view-loader'
|
|
17
22
|
import { safeCustomElement } from '../shared/safe-custom-element'
|
|
18
23
|
import { CoreLitElement } from '../styles'
|
|
19
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Raw transaction input type - accepts transactions with JSON, BigintJSON, or bigint values
|
|
27
|
+
*/
|
|
28
|
+
export type RawTransactionInput = Transaction | Record<string, any>
|
|
29
|
+
|
|
20
30
|
/**
|
|
21
31
|
* Lit Transaction Playback Component
|
|
22
32
|
*
|
|
23
|
-
* Provides index-based rendering of transactions with support for batch navigation
|
|
24
|
-
*
|
|
33
|
+
* Provides index-based rendering of transactions with support for batch navigation,
|
|
34
|
+
* context-aware view matching, and local transaction decoding.
|
|
35
|
+
*
|
|
36
|
+
* **Transaction Input:**
|
|
37
|
+
* - Pass a decoded transaction via `transaction` prop, OR
|
|
38
|
+
* - Pass a raw transaction via `rawTransaction` + `chain` props for local decoding
|
|
39
|
+
* - Raw transactions can have JSON, BigintJSON ("123n"), or bigint values
|
|
25
40
|
*
|
|
26
41
|
* **Single Transaction:**
|
|
27
42
|
* - index="0" → renders the transaction
|
|
@@ -45,38 +60,38 @@ import { CoreLitElement } from '../styles'
|
|
|
45
60
|
*
|
|
46
61
|
* @example
|
|
47
62
|
* ```html
|
|
48
|
-
* <!--
|
|
63
|
+
* <!-- With decoded transaction -->
|
|
49
64
|
* <transaction-playback
|
|
50
|
-
* .transaction="${
|
|
65
|
+
* .transaction="${decodedTransaction}"
|
|
51
66
|
* index="1"
|
|
52
67
|
* context="feed"
|
|
53
68
|
* variant="compact"
|
|
54
|
-
* @header-info="${(e) => console.log('Header:', e.detail)}"
|
|
55
69
|
* ></transaction-playback>
|
|
56
70
|
*
|
|
57
|
-
* <!--
|
|
71
|
+
* <!-- With raw transaction (local decoding) -->
|
|
58
72
|
* <transaction-playback
|
|
59
|
-
* .
|
|
73
|
+
* .rawTransaction="${rawTx}"
|
|
74
|
+
* .chain="${lukso}"
|
|
60
75
|
* index="1"
|
|
61
76
|
* context="approval"
|
|
62
77
|
* variant="full"
|
|
63
78
|
* ></transaction-playback>
|
|
64
|
-
*
|
|
65
|
-
* <!-- Batch summary: collapsed view -->
|
|
66
|
-
* <transaction-playback
|
|
67
|
-
* .transaction="${transaction}"
|
|
68
|
-
* index="0"
|
|
69
|
-
* context="batch-summary"
|
|
70
|
-
* variant="collapsed"
|
|
71
|
-
* ></transaction-playback>
|
|
72
79
|
* ```
|
|
73
80
|
*/
|
|
74
81
|
@safeCustomElement('transaction-playback')
|
|
75
82
|
export class TransactionPlayback extends CoreLitElement {
|
|
76
|
-
/** The
|
|
83
|
+
/** The decoded transaction to display */
|
|
77
84
|
@property({ type: Object })
|
|
78
85
|
transaction?: DecoderResult
|
|
79
86
|
|
|
87
|
+
/** Raw transaction to decode internally (alternative to passing decoded transaction) */
|
|
88
|
+
@property({ type: Object })
|
|
89
|
+
rawTransaction?: RawTransactionInput
|
|
90
|
+
|
|
91
|
+
/** Chain configuration for decoding (required when using rawTransaction) */
|
|
92
|
+
@property({ type: Object })
|
|
93
|
+
chain?: Chain
|
|
94
|
+
|
|
80
95
|
/** Index to display (0, 1, 2, ...) */
|
|
81
96
|
@property({ type: Number })
|
|
82
97
|
index = 1 // Default to index 1 (main transaction, skips batch summary)
|
|
@@ -106,6 +121,9 @@ export class TransactionPlayback extends CoreLitElement {
|
|
|
106
121
|
@state()
|
|
107
122
|
private isLoading = false
|
|
108
123
|
|
|
124
|
+
@state()
|
|
125
|
+
private isDecoding = false
|
|
126
|
+
|
|
109
127
|
@state()
|
|
110
128
|
private error?: string
|
|
111
129
|
|
|
@@ -115,13 +133,29 @@ export class TransactionPlayback extends CoreLitElement {
|
|
|
115
133
|
@state()
|
|
116
134
|
private headerInfo?: TransactionHeaderInfo
|
|
117
135
|
|
|
136
|
+
@state()
|
|
137
|
+
private decodedTransaction?: DecoderResult
|
|
138
|
+
|
|
118
139
|
private componentContainerRef: Ref<HTMLDivElement> = createRef()
|
|
119
140
|
private loader = getGlobalLitLoader()
|
|
141
|
+
private decodingUnsubscribe?: () => void
|
|
120
142
|
|
|
121
143
|
protected willUpdate(changedProperties: PropertyValues): void {
|
|
144
|
+
// Decode raw transaction if provided
|
|
145
|
+
if (
|
|
146
|
+
changedProperties.has('rawTransaction') ||
|
|
147
|
+
changedProperties.has('chain')
|
|
148
|
+
) {
|
|
149
|
+
if (this.rawTransaction) {
|
|
150
|
+
this.decodeRawTransaction()
|
|
151
|
+
return // Don't load view yet, wait for decoding
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
122
155
|
// Reload when transaction, index, context, or variant changes
|
|
123
156
|
if (
|
|
124
157
|
changedProperties.has('transaction') ||
|
|
158
|
+
changedProperties.has('decodedTransaction') ||
|
|
125
159
|
changedProperties.has('index') ||
|
|
126
160
|
changedProperties.has('context') ||
|
|
127
161
|
changedProperties.has('variant')
|
|
@@ -155,6 +189,102 @@ export class TransactionPlayback extends CoreLitElement {
|
|
|
155
189
|
TransactionViewEvents.HEADER_INFO,
|
|
156
190
|
this.handleHeaderInfo as EventListener
|
|
157
191
|
)
|
|
192
|
+
// Clean up decoding subscription
|
|
193
|
+
if (this.decodingUnsubscribe) {
|
|
194
|
+
this.decodingUnsubscribe()
|
|
195
|
+
this.decodingUnsubscribe = undefined
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Decode a raw transaction locally (no server API calls)
|
|
201
|
+
* Accepts transactions with JSON, BigintJSON, or bigint values
|
|
202
|
+
*
|
|
203
|
+
* Two-phase decoding:
|
|
204
|
+
* 1. Immediate sync decoding - shows basic decoded transaction right away
|
|
205
|
+
* 2. Async enhancement - progressively enhances with additional data
|
|
206
|
+
*/
|
|
207
|
+
private async decodeRawTransaction() {
|
|
208
|
+
if (!this.rawTransaction) {
|
|
209
|
+
return
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (!this.chain) {
|
|
213
|
+
this.error =
|
|
214
|
+
'Chain configuration is required when decoding raw transactions'
|
|
215
|
+
return
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
this.isDecoding = true
|
|
219
|
+
this.error = undefined
|
|
220
|
+
this.decodedTransaction = undefined
|
|
221
|
+
|
|
222
|
+
// Clean up previous subscription
|
|
223
|
+
if (this.decodingUnsubscribe) {
|
|
224
|
+
this.decodingUnsubscribe()
|
|
225
|
+
this.decodingUnsubscribe = undefined
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
try {
|
|
229
|
+
// Normalize the transaction input (convert BigintJSON strings to BigInt)
|
|
230
|
+
const normalizedTx = JSONbigString.read(this.rawTransaction)
|
|
231
|
+
|
|
232
|
+
// Decode the transaction locally with async enhancement enabled
|
|
233
|
+
// This returns immediately with sync-decoded result, then enhances asynchronously
|
|
234
|
+
const result = await decodeTransaction(normalizedTx, {
|
|
235
|
+
chain: this.chain,
|
|
236
|
+
plugins: [], // Use auto-registered plugins
|
|
237
|
+
schemaPlugins: [], // Use auto-registered schema plugins
|
|
238
|
+
wrappers: [], // No wrapper detection needed for raw transactions
|
|
239
|
+
async: true, // Enable async enhancement (ABI fetching, address resolution)
|
|
240
|
+
})
|
|
241
|
+
|
|
242
|
+
// Handle single transaction result (not batch)
|
|
243
|
+
if (!Array.isArray(result)) {
|
|
244
|
+
// PHASE 1: Store the immediate sync-decoded result and show it right away
|
|
245
|
+
this.decodedTransaction = result.immediate
|
|
246
|
+
this.isDecoding = false
|
|
247
|
+
|
|
248
|
+
// Load the view with the immediate result
|
|
249
|
+
this.loadView()
|
|
250
|
+
|
|
251
|
+
// PHASE 2: Subscribe to async enhancement updates
|
|
252
|
+
// The signal will emit updates as async decoding progresses
|
|
253
|
+
this.decodingUnsubscribe = result.signal.subscribe((state: any) => {
|
|
254
|
+
if (state.data && state.data !== this.decodedTransaction) {
|
|
255
|
+
this.decodedTransaction = state.data
|
|
256
|
+
// Re-render the view with enhanced data
|
|
257
|
+
this.loadView()
|
|
258
|
+
}
|
|
259
|
+
})
|
|
260
|
+
} else {
|
|
261
|
+
// For batch transactions, use the first result
|
|
262
|
+
const firstResult = result[0]
|
|
263
|
+
|
|
264
|
+
// PHASE 1: Immediate result
|
|
265
|
+
this.decodedTransaction = firstResult.immediate
|
|
266
|
+
this.isDecoding = false
|
|
267
|
+
|
|
268
|
+
// Load the view with the immediate result
|
|
269
|
+
this.loadView()
|
|
270
|
+
|
|
271
|
+
// PHASE 2: Subscribe to async enhancement updates
|
|
272
|
+
this.decodingUnsubscribe = firstResult.signal.subscribe(
|
|
273
|
+
(state: any) => {
|
|
274
|
+
if (state.data && state.data !== this.decodedTransaction) {
|
|
275
|
+
this.decodedTransaction = state.data
|
|
276
|
+
// Re-render the view with enhanced data
|
|
277
|
+
this.loadView()
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
)
|
|
281
|
+
}
|
|
282
|
+
} catch (err) {
|
|
283
|
+
this.error =
|
|
284
|
+
err instanceof Error ? err.message : 'Failed to decode transaction'
|
|
285
|
+
this.isDecoding = false
|
|
286
|
+
console.error('Transaction decoding error:', err)
|
|
287
|
+
}
|
|
158
288
|
}
|
|
159
289
|
|
|
160
290
|
private handleHeaderInfo = (event: Event): void => {
|
|
@@ -173,7 +303,10 @@ export class TransactionPlayback extends CoreLitElement {
|
|
|
173
303
|
}
|
|
174
304
|
|
|
175
305
|
private async loadView() {
|
|
176
|
-
if (
|
|
306
|
+
// Use decodedTransaction if available (from rawTransaction), otherwise use passed transaction
|
|
307
|
+
const txToDisplay = this.decodedTransaction || this.transaction
|
|
308
|
+
|
|
309
|
+
if (!txToDisplay) {
|
|
177
310
|
this.error = 'No transaction provided'
|
|
178
311
|
return
|
|
179
312
|
}
|
|
@@ -185,7 +318,7 @@ export class TransactionPlayback extends CoreLitElement {
|
|
|
185
318
|
|
|
186
319
|
try {
|
|
187
320
|
// Create playback state
|
|
188
|
-
this.playbackState = createTransactionPlayback(
|
|
321
|
+
this.playbackState = createTransactionPlayback(txToDisplay, {
|
|
189
322
|
framework: 'lit',
|
|
190
323
|
fallbackViewId: this.fallbackViewId,
|
|
191
324
|
context: this.context,
|
|
@@ -323,6 +456,16 @@ export class TransactionPlayback extends CoreLitElement {
|
|
|
323
456
|
}
|
|
324
457
|
|
|
325
458
|
render() {
|
|
459
|
+
// Decoding state
|
|
460
|
+
if (this.isDecoding) {
|
|
461
|
+
return html`
|
|
462
|
+
<div class="flex flex-col items-center justify-center py-15 px-5 text-neutral-60">
|
|
463
|
+
<div class="text-32 mb-4 animate-spin">🔄</div>
|
|
464
|
+
<div class="text-16 font-500">Decoding transaction...</div>
|
|
465
|
+
</div>
|
|
466
|
+
`
|
|
467
|
+
}
|
|
468
|
+
|
|
326
469
|
// Loading state
|
|
327
470
|
if (this.isLoading) {
|
|
328
471
|
return html`
|