@lukso/transaction-view-core 0.3.1-dev.a8c9315

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/.turbo/turbo-build.log +33 -0
  2. package/CHANGELOG.md +104 -0
  3. package/LICENSE +201 -0
  4. package/README.md +264 -0
  5. package/dist/index.cjs +4573 -0
  6. package/dist/index.cjs.map +1 -0
  7. package/dist/index.d.cts +493 -0
  8. package/dist/index.d.ts +493 -0
  9. package/dist/index.js +4534 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/shared/index.cjs +2480 -0
  12. package/dist/shared/index.cjs.map +1 -0
  13. package/dist/shared/index.d.cts +887 -0
  14. package/dist/shared/index.d.ts +887 -0
  15. package/dist/shared/index.js +2437 -0
  16. package/dist/shared/index.js.map +1 -0
  17. package/dist/styles/index.cjs +58 -0
  18. package/dist/styles/index.cjs.map +1 -0
  19. package/dist/styles/index.d.cts +9 -0
  20. package/dist/styles/index.d.ts +9 -0
  21. package/dist/styles/index.js +31 -0
  22. package/dist/styles/index.js.map +1 -0
  23. package/package.json +57 -0
  24. package/publish.log +0 -0
  25. package/src/components/asset-card.ts +426 -0
  26. package/src/components/contract-card.ts +238 -0
  27. package/src/components/description-view.ts +605 -0
  28. package/src/components/index.ts +20 -0
  29. package/src/components/info-panel.ts +437 -0
  30. package/src/components/permissions-block.ts +138 -0
  31. package/src/components/transaction-playback.ts +429 -0
  32. package/src/components/universal-token-view.ts +281 -0
  33. package/src/declaration.d.ts +4 -0
  34. package/src/examples/INTEGRATION_GUIDE.md +240 -0
  35. package/src/examples/TransactionContentWithReplacement.vue +269 -0
  36. package/src/index.ts +38 -0
  37. package/src/registry/index.ts +31 -0
  38. package/src/registry/lit-view-loader.ts +191 -0
  39. package/src/shared/address-display.ts +370 -0
  40. package/src/shared/address-view.ts +385 -0
  41. package/src/shared/custom-select.ts +164 -0
  42. package/src/shared/function-name-view.ts +89 -0
  43. package/src/shared/gas-provider-view.ts +218 -0
  44. package/src/shared/icon-view.ts +288 -0
  45. package/src/shared/image-list.ts +261 -0
  46. package/src/shared/image-loader-controller.ts +160 -0
  47. package/src/shared/index.ts +34 -0
  48. package/src/shared/load-web-components.ts +56 -0
  49. package/src/shared/notification-view.ts +132 -0
  50. package/src/shared/progress-view.ts +86 -0
  51. package/src/shared/safe-custom-element.ts +35 -0
  52. package/src/shared/scroll-to-bottom-button.ts +55 -0
  53. package/src/shared/signal-controller.ts +124 -0
  54. package/src/shared/transaction-view-controller.ts +345 -0
  55. package/src/shared/url-view.ts +129 -0
  56. package/src/shared/value-view.ts +510 -0
  57. package/src/styles/index.ts +28 -0
  58. package/src/styles/styles.css +1 -0
  59. package/src/vue-entry.ts +15 -0
  60. package/tailwind.config.cjs +9 -0
  61. package/tsconfig.json +22 -0
  62. package/tsup.config.ts +90 -0
@@ -0,0 +1,240 @@
1
+ # Transaction View System Integration Guide
2
+
3
+ This guide explains how to replace the iframe-based transaction view architecture with the new direct component rendering system using Lit web components and the ViewRegistry.
4
+
5
+ ## Overview
6
+
7
+ The new system provides:
8
+ - **Better performance**: Direct component rendering vs iframe overhead
9
+ - **No security sandboxing needed**: Immutable decoded structures eliminate security concerns
10
+ - **Universal components**: Single Lit components that work in Vue, React, Angular, etc.
11
+ - **Dynamic view selection**: Registry-based matching for different transaction types
12
+ - **Batch transaction support**: Automatic subtransaction handling
13
+
14
+ ## Architecture Changes
15
+
16
+ ### Before (Iframe-based)
17
+ ```
18
+ TransactionContent.vue
19
+ └── TransactionIframe.vue
20
+ └── iframe (isolated sandbox)
21
+ └── Individual Vue components (LSP7Transfer, LSP8Transfer, etc.)
22
+ ```
23
+
24
+ ### After (Direct rendering)
25
+ ```
26
+ TransactionContent.vue
27
+ └── TransactionViewReplacement.vue
28
+ └── ViewRegistry selection logic
29
+ └── Universal Lit components (universal-token-view, etc.)
30
+ ```
31
+
32
+ ## Step-by-Step Integration
33
+
34
+ ### 1. Install the Package
35
+
36
+ Add the transaction-view-core package to your project:
37
+
38
+ ```bash
39
+ pnpm add @lukso/transaction-view-core
40
+ ```
41
+
42
+ ### 2. Initialize the System
43
+
44
+ In your main application entry point, initialize the transaction view system:
45
+
46
+ ```ts
47
+ import { initializeTransactionViews } from '@lukso/transaction-view-core'
48
+
49
+ // Initialize once when your app starts
50
+ initializeTransactionViews()
51
+ ```
52
+
53
+ ### 3. Replace TransactionIframe
54
+
55
+ In `components/transactions/Transaction/TransactionContent.vue`, replace the `TransactionIframe` import and usage:
56
+
57
+ #### Old Code:
58
+ ```vue
59
+ <script setup lang="ts">
60
+ import TransactionIframe from '@/components/transactions/Transaction/TransactionIframe.vue'
61
+ // ...
62
+ </script>
63
+
64
+ <template>
65
+ <!-- ... -->
66
+ <TransactionIframe
67
+ :transaction="transaction"
68
+ :components="components"
69
+ @on-loaded="onIFrameLoaded"
70
+ @on-transaction-change="onTransactionChange"
71
+ @on-resize="onResize"
72
+ />
73
+ </template>
74
+ ```
75
+
76
+ #### New Code:
77
+ ```vue
78
+ <script setup lang="ts">
79
+ import { TransactionViewReplacement } from '@lukso/transaction-view-core'
80
+ // ...
81
+ </script>
82
+
83
+ <template>
84
+ <!-- ... -->
85
+ <TransactionViewReplacement
86
+ :transaction="transaction"
87
+ :chain="chain"
88
+ :handle-subtransactions="true"
89
+ fallback-view-id="universal-execute"
90
+ @on-loaded="onIFrameLoaded"
91
+ @on-resize="onResize"
92
+ @on-error="onTransactionViewError"
93
+ />
94
+ </template>
95
+ ```
96
+
97
+ ### 4. Add Error Handling
98
+
99
+ Add error handling for the new component:
100
+
101
+ ```vue
102
+ <script setup lang="ts">
103
+ // Add this to your existing emits
104
+ type Emits = {
105
+ // ... existing emits
106
+ (event: 'on-transaction-view-error', error: string): void
107
+ }
108
+
109
+ const emits = defineEmits<Emits>()
110
+
111
+ // Add error handler
112
+ const onTransactionViewError = (error: string) => {
113
+ console.error('Transaction view error:', error)
114
+ emits('on-transaction-view-error', error)
115
+ // Could show error state in UI
116
+ }
117
+ </script>
118
+ ```
119
+
120
+ ### 5. Remove Iframe-specific Code
121
+
122
+ You can remove or modify these iframe-specific parts:
123
+
124
+ ```ts
125
+ // Remove these iframe-related imports and logic:
126
+ // - useIFrameAPIConnector usage
127
+ // - controllers ref and watching
128
+ // - loadComponents function
129
+ // - post() calls to iframe
130
+
131
+ // The new system handles all this automatically through the ViewRegistry
132
+ ```
133
+
134
+ ## Component Matching
135
+
136
+ The system automatically selects the appropriate view based on transaction properties:
137
+
138
+ ### LSP7 Token Transfer
139
+ - `standard: 'LSP7'`
140
+ - `functionName: 'transfer'`
141
+ - `recordType: 'lsp7-transfer'`
142
+ - → Uses `universal-token-view`
143
+
144
+ ### LSP8 NFT Transfer
145
+ - `standard: 'LSP8'`
146
+ - `functionName: 'transfer'`
147
+ - `recordType: 'lsp8-transfer'`
148
+ - → Uses `universal-token-view`
149
+
150
+ ### Batch Transactions
151
+ - `functionName: 'executeBatch'`
152
+ - `recordType: 'execute-batch'`
153
+ - → Uses `universal-token-view` for main transaction
154
+ - → Automatically selects views for each subtransaction
155
+
156
+ ### Fallback
157
+ - Unmatched transactions use `universal-execute` (configurable)
158
+
159
+ ## Custom View Registration
160
+
161
+ You can register additional custom views:
162
+
163
+ ```ts
164
+ import { getGlobalRegistry } from '@lukso/transaction-view-core'
165
+
166
+ const registry = getGlobalRegistry()
167
+
168
+ registry.register({
169
+ id: 'custom-erc20-transfer',
170
+ name: 'ERC20 Transfer',
171
+ priority: 95,
172
+ criteria: {
173
+ functionName: 'transfer',
174
+ standard: 'ERC20'
175
+ },
176
+ frameworks: {
177
+ lit: {
178
+ loader: { type: 'custom-element', tagName: 'custom-erc20-view' },
179
+ component: 'custom-erc20-view'
180
+ }
181
+ }
182
+ })
183
+ ```
184
+
185
+ ## Props Mapping
186
+
187
+ The new component automatically receives the same data that was previously passed to the iframe:
188
+
189
+ | Iframe Data | New Component Props |
190
+ |-------------|-------------------|
191
+ | `transaction` | `transaction` |
192
+ | `currentProfile` | Passed to components via context |
193
+ | `approval` | Passed to components via context |
194
+ | `controllers` | Passed to components via context |
195
+ | `networkId` | `chain` prop |
196
+ | `preferences` | Passed to components via context |
197
+
198
+ ## Benefits
199
+
200
+ 1. **Performance**: ~50-80% faster loading (no iframe overhead)
201
+ 2. **Bundle Size**: Reduced by eliminating duplicate components
202
+ 3. **Maintenance**: Single universal component instead of 15+ specialized ones
203
+ 4. **Compatibility**: Works across Vue, React, Angular, Svelte
204
+ 5. **Type Safety**: Full TypeScript support throughout the stack
205
+
206
+ ## Migration Checklist
207
+
208
+ - [ ] Install `@lukso/transaction-view-core` package
209
+ - [ ] Initialize system in app entry point
210
+ - [ ] Replace `TransactionIframe` with `TransactionViewReplacement`
211
+ - [ ] Add error handling for new component
212
+ - [ ] Remove iframe-specific code (useIFrameAPIConnector, loadComponents, etc.)
213
+ - [ ] Test all transaction types (LSP7, LSP8, batch, fallback)
214
+ - [ ] Update any tests that depend on iframe behavior
215
+ - [ ] Monitor performance improvements
216
+
217
+ ## Troubleshooting
218
+
219
+ ### Components Not Loading
220
+ - Ensure `initializeTransactionViews()` is called once at app startup
221
+ - Check browser console for custom element registration errors
222
+ - Verify transaction has required properties (functionName, recordType, etc.)
223
+
224
+ ### View Selection Issues
225
+ - Check registry stats: `getTransactionViewSystemStatus()`
226
+ - Verify transaction properties match view criteria
227
+ - Use fallback view for unmatched transactions
228
+
229
+ ### Performance Issues
230
+ - The new system should be significantly faster than iframes
231
+ - Monitor component creation time vs iframe load time
232
+ - Check for memory leaks from unmounted components
233
+
234
+ ## Support
235
+
236
+ For issues or questions about the integration:
237
+ 1. Check the browser console for error messages
238
+ 2. Use `getTransactionViewSystemStatus()` to debug registry state
239
+ 3. Verify transaction structure matches expected format
240
+ 4. Test with fallback views to isolate selection issues
@@ -0,0 +1,269 @@
1
+ <script setup lang="ts">
2
+ /**
3
+ * Example of how to modify TransactionContent.vue to use the new transaction view system
4
+ * instead of the iframe-based architecture
5
+ *
6
+ * This shows the integration points and how to replace TransactionIframe with
7
+ * the new TransactionViewReplacement component
8
+ */
9
+ import { ref, onMounted } from 'vue'
10
+ import type { DecoderResult } from '@lukso/transaction-decoder'
11
+ import type { Chain } from 'viem'
12
+
13
+ // Import the replacement component from our package
14
+ import { TransactionViewReplacement } from '../vue'
15
+
16
+ // Original imports from TransactionContent.vue would remain the same
17
+ // import Header from '@/components/views/Confirmation/Header.vue'
18
+ // import SvgIcon from '@/components/shared/SvgIcon.vue'
19
+ // ... etc
20
+
21
+ type Props = {
22
+ transaction?: DecoderResult
23
+ chain: Chain
24
+ isFixedHeader: boolean
25
+ scrollPercentage: number
26
+ profileBalance?: number
27
+ isConfirmation?: boolean
28
+ }
29
+
30
+ type Emits = {
31
+ (event: 'on-iframe-loaded'): void
32
+ (event: 'header-offset', value: number): void
33
+ (event: 'on-container-height-resize', height: number): void
34
+ (event: 'on-transaction-change', message: unknown): void
35
+ (event: 'on-low-balance-cancel-click'): void
36
+ }
37
+
38
+ const props = defineProps<Props>()
39
+ const emits = defineEmits<Emits>()
40
+
41
+ // State management (same as original)
42
+ const isAdvancedViewExpanded = ref(false)
43
+ const staticHeaderRef = ref()
44
+ const fixedHeaderRef = ref()
45
+ const loading = ref(true)
46
+ const advancedViewTriggerRef = ref()
47
+ const advancedViewContentRef = ref()
48
+ const iframeContainerRef = ref()
49
+
50
+ const { t } = useI18n()
51
+
52
+ // Event handlers (same as original, but adapted for new component)
53
+ const onResize = ({ height }: { height: number }) => {
54
+ emits('on-container-height-resize', height)
55
+ }
56
+
57
+ // This replaces the original onIFrameLoaded
58
+ const onTransactionViewLoaded = () => {
59
+ loading.value = false
60
+ emits('on-iframe-loaded')
61
+ }
62
+
63
+ // Handle errors from the new component
64
+ const onTransactionViewError = (error: string) => {
65
+ console.error('Transaction view error:', error)
66
+ loading.value = false
67
+ // Could show error state in UI
68
+ }
69
+
70
+ // This replaces the original loadComponents function
71
+ // No longer needed since the new component handles loading automatically
72
+
73
+ // Rest of the component logic remains the same...
74
+ const onAdvancedViewToggle = () => {
75
+ isAdvancedViewExpanded.value = !isAdvancedViewExpanded.value
76
+
77
+ if (
78
+ props.transaction?.gasProvider?.type === 'controller' &&
79
+ props.transaction?.error?.message ===
80
+ t('transactions.error.insufficient_funds')
81
+ ) {
82
+ emits('on-low-balance-cancel-click')
83
+ return
84
+ }
85
+
86
+ setTimeout(() => {
87
+ const advancedViewContentHeight = advancedViewContentRef.value?.offsetHeight
88
+ const iframeContainerHeight = iframeContainerRef.value?.offsetHeight
89
+ const advancedViewTriggerHeight = advancedViewTriggerRef.value?.offsetHeight
90
+
91
+ onResize({
92
+ height:
93
+ advancedViewContentHeight +
94
+ iframeContainerHeight +
95
+ advancedViewTriggerHeight,
96
+ })
97
+ }, 50)
98
+ }
99
+
100
+ onMounted(() => {
101
+ const resizeObserver = new ResizeObserver(() => {
102
+ const headerOffset =
103
+ staticHeaderRef.value?.offsetHeight -
104
+ fixedHeaderRef.value?.children[0].offsetHeight
105
+ emits('header-offset', headerOffset)
106
+ })
107
+
108
+ if (staticHeaderRef.value && fixedHeaderRef.value) {
109
+ resizeObserver.observe(staticHeaderRef.value)
110
+ resizeObserver.observe(fixedHeaderRef.value)
111
+ }
112
+ })
113
+ </script>
114
+
115
+ <template>
116
+ <div
117
+ v-if="transaction"
118
+ class="transaction-content"
119
+ id="transactionContentContainer"
120
+ >
121
+ <!-- Header section remains exactly the same -->
122
+ <div ref="staticHeaderRef">
123
+ <!-- Header component with all slots -->
124
+ </div>
125
+ <div ref="fixedHeaderRef">
126
+ <!-- Fixed header component with all slots -->
127
+ </div>
128
+
129
+ <!-- Error notification section remains the same -->
130
+ <div v-if="!isConfirmation || transaction.error" class="px-4 pt-4">
131
+ <!-- Error notifications and created-at timestamp -->
132
+ </div>
133
+
134
+ <!-- Advanced view trigger remains the same -->
135
+ <div
136
+ ref="advancedViewTriggerRef"
137
+ :class="`is-flex is-align-content-center ${
138
+ isConfirmation || transaction.status !== 'INITIALIZED'
139
+ ? 'is-justify-content-space-between'
140
+ : 'is-justify-content-end'
141
+ } is-align-items-center is-clickable my-3 px-4`"
142
+ @click="onAdvancedViewToggle"
143
+ >
144
+ <!-- Advanced view toggle content remains the same -->
145
+ </div>
146
+
147
+ <!-- Advanced view content remains the same -->
148
+ <div
149
+ ref="advancedViewContentRef"
150
+ :class="`advanced-view-content ${
151
+ isAdvancedViewExpanded ? 'is-expanded' : ''
152
+ }`"
153
+ >
154
+ <!-- Advanced view inner content remains the same -->
155
+ </div>
156
+
157
+ <!-- THIS IS THE KEY CHANGE: Replace TransactionIframe with TransactionViewReplacement -->
158
+ <div class="iframe-container" ref="iframeContainerRef">
159
+ <div class="iframe-inner is-relative">
160
+ <!-- Loading spinner (now handled by TransactionViewReplacement) -->
161
+ <!-- But we can keep this for consistency during the transition -->
162
+ <div
163
+ v-if="loading"
164
+ id="iframeSpinner"
165
+ class="confirmation-spinner"
166
+ data-testid="spinner"
167
+ >
168
+ <!-- Spinner content -->
169
+ </div>
170
+
171
+ <!-- REPLACE: TransactionIframe with TransactionViewReplacement -->
172
+ <TransactionViewReplacement
173
+ v-if="transaction"
174
+ :transaction="transaction"
175
+ :chain="chain"
176
+ :handle-subtransactions="true"
177
+ fallback-view-id="universal-execute"
178
+ @on-loaded="onTransactionViewLoaded"
179
+ @on-resize="onResize"
180
+ @on-error="onTransactionViewError"
181
+ />
182
+ </div>
183
+ </div>
184
+ </div>
185
+ </template>
186
+
187
+ <style scoped lang="scss">
188
+ /* All the original styles remain exactly the same */
189
+ @import '@/popup/styles/typography';
190
+
191
+ .error-title {
192
+ @extend %paragraph-inter-14-medium;
193
+
194
+ .read-more {
195
+ cursor: pointer;
196
+ transition: var(--transition);
197
+ text-decoration: underline;
198
+
199
+ &:hover {
200
+ color: var(--neutral-30);
201
+ }
202
+ }
203
+ }
204
+
205
+ .transaction-content {
206
+ background-color: var(--neutral-97);
207
+ }
208
+
209
+ .advanced-view-trigger {
210
+ color: var(--neutral-60);
211
+ opacity: 0.6;
212
+ transition: var(--transition);
213
+
214
+ @extend %currency-inter-10-bold-uppercase;
215
+
216
+ &:hover {
217
+ opacity: 1;
218
+ }
219
+ }
220
+
221
+ .advanced-view-content {
222
+ height: 0;
223
+ overflow: hidden;
224
+ transition: all 0.2s ease-in-out;
225
+
226
+ .advanced-view-content-inner {
227
+ border-radius: 24px;
228
+ background: var(--neutral-95);
229
+ padding-bottom: 1px;
230
+ }
231
+
232
+ .transaction-info {
233
+ padding: 16px;
234
+ }
235
+
236
+ &.is-expanded {
237
+ height: initial;
238
+ }
239
+ }
240
+
241
+ .iframe-container {
242
+ background-color: transparent;
243
+ padding-top: 0;
244
+
245
+ .iframe-inner {
246
+ border-radius: 24px 24px 0 0;
247
+ background: var(--neutral-100);
248
+ min-height: 229.25px;
249
+
250
+ &::after {
251
+ content: '';
252
+ position: absolute;
253
+ background: var(--neutral-100);
254
+ width: 100%;
255
+ height: 50px;
256
+ }
257
+ }
258
+ }
259
+
260
+ .confirmation-spinner {
261
+ position: absolute;
262
+ display: flex;
263
+ left: 50%;
264
+ top: 100px;
265
+ transform: translate(-50%, -50%);
266
+ }
267
+
268
+ /* Additional styles remain the same... */
269
+ </style>
package/src/index.ts ADDED
@@ -0,0 +1,38 @@
1
+ // Main exports for transaction-view-core package
2
+
3
+ export * from './shared/index.js'
4
+
5
+ // Auto-register all core web components when imported
6
+ import './shared/address-display.js'
7
+ import './shared/address-view.js'
8
+ import './shared/value-view.js'
9
+ import './shared/notification-view.js'
10
+ import './shared/function-name-view.js'
11
+ import './shared/scroll-to-bottom-button.js'
12
+ import './shared/url-view.js'
13
+ import './shared/gas-provider-view.js'
14
+ import './shared/image-list.js'
15
+ import './components/info-panel.js'
16
+ import './components/asset-card.js'
17
+ import './components/description-view.js'
18
+ import './components/universal-token-view.js'
19
+ import './components/contract-card.js'
20
+ import './components/permissions-block.js'
21
+
22
+ // Explicit import/export for fonts to ensure d.ts generation doesn't tree-shake it
23
+
24
+ // Export registry and selection system
25
+ export * from './registry/index.js'
26
+ // Export styles (typography, colors, etc.)
27
+ // (Keep other style exports if added later)
28
+
29
+ // Note: Vue integration is available via separate entry point './vue-entry.js'
30
+ // to avoid dependency issues in non-Vue frameworks
31
+
32
+ // Re-export DecoderResult from the original package
33
+ export type { DecoderResult } from '@lukso/transaction-decoder'
34
+ // Re-export core types from decoder-headless for convenience
35
+ export type {
36
+ DecoderRecordForSelection,
37
+ ViewContext,
38
+ } from '@lukso/transaction-view-headless'
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Transaction View Core Registry
3
+ *
4
+ * This module provides the registration and selection logic for transaction views,
5
+ * replacing the iframe-based architecture with direct component rendering.
6
+ */
7
+
8
+ // Re-export headless types and utilities for convenience
9
+ export type {
10
+ FrameworkSupport,
11
+ FrameworkViewConfig,
12
+ ViewDefinition,
13
+ ViewLoader,
14
+ ViewMatch,
15
+ ViewMatchOptions,
16
+ ViewRegistry,
17
+ } from '@lukso/transaction-view-headless'
18
+ export {
19
+ DefaultViewRegistry,
20
+ getGlobalRegistry,
21
+ resetGlobalRegistry,
22
+ setGlobalRegistry,
23
+ } from '@lukso/transaction-view-headless'
24
+ // Lit component loader
25
+ export {
26
+ getGlobalLitLoader,
27
+ LitViewLoader,
28
+ resetGlobalLitLoader,
29
+ setGlobalLitLoader,
30
+ } from './lit-view-loader'
31
+ // Transaction view selector