@lukso/transaction-view-headless 0.4.3-dev.661418d → 0.4.3-dev.a07a66f

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 (39) hide show
  1. package/.turbo/turbo-build.log +31 -29
  2. package/ARG_ACCESS_PATTERN.md +265 -0
  3. package/CONTEXT_VARIANT_GUIDE.md +4 -4
  4. package/EVENT_SYSTEM_SUMMARY.md +601 -0
  5. package/HEADER_EVENTS_GUIDE.md +291 -0
  6. package/RECOMPOSITION_REFERENCE.md +303 -0
  7. package/TRANSACTION_MODIFICATION_GUIDE.md +927 -0
  8. package/dist/composables/index.cjs +1 -1
  9. package/dist/composables/index.cjs.map +1 -1
  10. package/dist/composables/index.d.cts +3 -3
  11. package/dist/composables/index.d.ts +3 -3
  12. package/dist/composables/index.js +1 -1
  13. package/dist/composables/index.js.map +1 -1
  14. package/dist/{index-CSDjhiKV.d.cts → index-BqL7xdDl.d.cts} +2 -2
  15. package/dist/{index-CMLU1hKL.d.ts → index-CNUHqRdk.d.ts} +2 -2
  16. package/dist/index.cjs +60 -1
  17. package/dist/index.cjs.map +1 -1
  18. package/dist/index.d.cts +5 -4
  19. package/dist/index.d.ts +5 -4
  20. package/dist/index.js +55 -1
  21. package/dist/index.js.map +1 -1
  22. package/dist/registry/index.d.cts +2 -2
  23. package/dist/registry/index.d.ts +2 -2
  24. package/dist/types/index.cjs +68 -0
  25. package/dist/types/index.cjs.map +1 -1
  26. package/dist/types/index.d.cts +229 -169
  27. package/dist/types/index.d.ts +229 -169
  28. package/dist/types/index.js +55 -0
  29. package/dist/types/index.js.map +1 -1
  30. package/dist/utils/index.d.cts +1 -1
  31. package/dist/utils/index.d.ts +1 -1
  32. package/dist/{view-loader-dD86QAlQ.d.cts → view-loader--mEEI8YY.d.ts} +1 -1
  33. package/dist/{view-loader-ii8AxiQR.d.ts → view-loader-D7ApWfdN.d.cts} +1 -1
  34. package/dist/view-matching-C9G3z8lQ.d.cts +203 -0
  35. package/dist/view-matching-C9G3z8lQ.d.ts +203 -0
  36. package/package.json +3 -3
  37. package/src/composables/use-transaction-playback.ts +8 -5
  38. package/src/types/index.ts +14 -0
  39. package/src/types/view-events.ts +322 -0
@@ -0,0 +1,203 @@
1
+ import { DecoderResult } from '@lukso/transaction-decoder';
2
+
3
+ /**
4
+ * Different contexts WHERE transaction views are displayed
5
+ *
6
+ * Context determines the environment/location, which affects:
7
+ * - Available space
8
+ * - User intent
9
+ * - Security requirements
10
+ * - Interaction patterns
11
+ */
12
+ type ViewContext = 'approval' | 'feed' | 'list' | 'detail' | 'review' | 'notification' | 'embed' | 'batch-summary';
13
+ /**
14
+ * Different variants of HOW transaction views are displayed
15
+ *
16
+ * Variant determines the presentation style within a context:
17
+ * - Same transaction can have different variants in different contexts
18
+ * - Example: 'collapsed' in feed vs 'collapsed' in approval are different
19
+ */
20
+ type ViewVariant = 'full' | 'collapsed' | 'minimal' | 'icon-only' | 'compact' | 'expanded' | string;
21
+ /**
22
+ * Context-specific display requirements
23
+ */
24
+ interface ViewContextRequirements {
25
+ /** Maximum height constraint */
26
+ maxHeight?: number;
27
+ /** Whether to show action buttons */
28
+ showActions?: boolean;
29
+ /** Level of detail to display */
30
+ detailLevel: 'minimal' | 'summary' | 'full' | 'debug';
31
+ /** Whether user can expand for more details */
32
+ expandable?: boolean;
33
+ /** Color scheme preference */
34
+ colorScheme?: 'light' | 'dark' | 'auto';
35
+ /** Whether to emphasize security warnings */
36
+ emphasizeSecurity?: boolean;
37
+ }
38
+
39
+ type DecoderRecordForSelection = DecoderResult & {
40
+ recordType?: string;
41
+ functionName?: string;
42
+ contractAddress?: string;
43
+ standard?: string;
44
+ };
45
+
46
+ /**
47
+ * Criteria that can be used to match transactions to views
48
+ */
49
+ interface ViewMatchCriteria {
50
+ /** LSP standard (e.g., 'LSP7', 'LSP8', 'LSP0') */
51
+ standard?: string | string[];
52
+ /** Function name from ABI (e.g., 'transfer', 'setData', 'execute') */
53
+ functionName?: string | string[];
54
+ /** Record type from decoder (e.g., 'lsp7-transfer', 'set-data') */
55
+ recordType?: string | string[];
56
+ /** Contract address (for specific contract implementations) */
57
+ contractAddress?: string | string[];
58
+ /** Chain ID (for network-specific views) */
59
+ chainId?: number | number[];
60
+ /** Display context (opt-in) - WHERE to display (feed, approval, list, etc.) */
61
+ context?: ViewContext | ViewContext[];
62
+ /** Display variant (opt-in) - HOW to display (collapsed, minimal, full, etc.) */
63
+ variant?: ViewVariant | ViewVariant[];
64
+ /** Context requirements (opt-in) - additional constraints for context matching */
65
+ contextRequirements?: Partial<ViewContextRequirements>;
66
+ /**
67
+ * Custom matcher function for complex synchronous logic.
68
+ * Returns the number of conditions that matched (higher = better match).
69
+ *
70
+ * IMPORTANT: Must be synchronous and only use data from DecoderResult.
71
+ * For async operations, populate transaction.custom in an enhancer.
72
+ *
73
+ * @returns Number of matching conditions (0 = no match, higher = stronger match)
74
+ *
75
+ * @example
76
+ * // Match token transfers (tokenType === 0)
77
+ * customMatcher: (tx) => {
78
+ * let matches = 0
79
+ * if (tx.custom?.tokenType === 0) matches++
80
+ * if (BigInt(tx.value || 0) > 0) matches++
81
+ * return matches
82
+ * }
83
+ */
84
+ customMatcher?: (transaction: DecoderResult) => number;
85
+ }
86
+ /**
87
+ * Framework-agnostic view definition
88
+ */
89
+ interface ViewDefinition {
90
+ /** Unique identifier for this view */
91
+ id: string;
92
+ /** Human-readable name */
93
+ name: string;
94
+ /** Criteria for matching transactions to this view */
95
+ criteria: ViewMatchCriteria;
96
+ /** Priority when multiple views match (higher = preferred) */
97
+ priority: number;
98
+ /** Supported frameworks for this view */
99
+ frameworks: FrameworkSupport;
100
+ /** Optional description */
101
+ description?: string;
102
+ }
103
+ /**
104
+ * Framework-specific loading configurations
105
+ *
106
+ * Strategic Framework Selection (Suffering Economics Optimized):
107
+ * - lit: Universal web components (works in Vue, React, Angular, Svelte, etc.)
108
+ * - vue: Native Vue components (optional, for Vue-specific optimizations)
109
+ * - rn: React Native components (mobile-native, optional - falls back to WebView)
110
+ *
111
+ * Lit is the universal fallback. Vue and React Native are optional native implementations
112
+ * that get priority when available in their respective environments.
113
+ */
114
+ interface FrameworkSupport {
115
+ lit: FrameworkViewConfig;
116
+ vue?: FrameworkViewConfig;
117
+ rn?: FrameworkViewConfig;
118
+ }
119
+ /**
120
+ * Configuration for loading a view in a specific framework
121
+ */
122
+ interface FrameworkViewConfig {
123
+ /** Loading method */
124
+ loader: ViewLoader;
125
+ /** Component name/identifier */
126
+ component: string;
127
+ /** Package where the component is located */
128
+ package?: string;
129
+ }
130
+ /**
131
+ * Different ways to load a view component
132
+ *
133
+ * Loaders support both static and lazy loading:
134
+ * - Static: `path: './Component.vue'` - bundled with app
135
+ * - Lazy: `path: () => import('./Component.vue')` - loaded on demand
136
+ */
137
+ type ViewLoader = {
138
+ type: 'dynamic-import';
139
+ path: string | (() => Promise<any>);
140
+ } | {
141
+ type: 'static-import';
142
+ path: string | (() => Promise<any>);
143
+ } | {
144
+ type: 'custom-element';
145
+ tagName: string;
146
+ } | {
147
+ type: 'registry-lookup';
148
+ registryKey: string;
149
+ } | {
150
+ type: 'custom';
151
+ loader: (config: FrameworkViewConfig) => Promise<any>;
152
+ };
153
+ /**
154
+ * Result of matching a transaction against registered views
155
+ */
156
+ interface ViewMatch {
157
+ /** The view definition that matched */
158
+ view: ViewDefinition;
159
+ /** Score indicating how well this view matches (0-1) */
160
+ score: number;
161
+ /** Which criteria matched */
162
+ matchedCriteria: (keyof ViewMatchCriteria)[];
163
+ /** Framework-specific loading config */
164
+ frameworkConfig?: FrameworkViewConfig;
165
+ }
166
+ /**
167
+ * Options for view matching
168
+ */
169
+ interface ViewMatchOptions {
170
+ /** Target framework */
171
+ framework: 'lit' | 'vue' | 'rn';
172
+ /** Display context (optional) - WHERE to display (feed, approval, list, etc.) */
173
+ context?: ViewContext;
174
+ /** Display variant (optional) - HOW to display (collapsed, minimal, full, etc.) */
175
+ variant?: ViewVariant;
176
+ /** Context requirements (optional) - additional constraints for context-aware matching */
177
+ contextRequirements?: Partial<ViewContextRequirements>;
178
+ /** Minimum score threshold (0-1) */
179
+ minScore?: number;
180
+ /** Maximum number of matches to return */
181
+ maxMatches?: number;
182
+ /** Whether to include framework config in results */
183
+ includeFrameworkConfig?: boolean;
184
+ }
185
+ /**
186
+ * Registry for managing view definitions
187
+ */
188
+ interface ViewRegistry {
189
+ /** Register a new view */
190
+ register(view: ViewDefinition): void;
191
+ /** Unregister a view by ID */
192
+ unregister(viewId: string): void;
193
+ /** Get all registered views */
194
+ getAllViews(): ViewDefinition[];
195
+ /** Find best matching views for a transaction */
196
+ findMatches(transaction: DecoderResult, options: ViewMatchOptions): ViewMatch[];
197
+ /** Get a specific view by ID */
198
+ getView(viewId: string): ViewDefinition | undefined;
199
+ /** Clear all registered views */
200
+ clear(): void;
201
+ }
202
+
203
+ export type { DecoderRecordForSelection as D, FrameworkSupport as F, ViewContext as V, ViewDefinition as a, ViewMatch as b, ViewMatchCriteria as c, ViewContextRequirements as d, ViewVariant as e, FrameworkViewConfig as f, ViewLoader as g, ViewMatchOptions as h, ViewRegistry as i };
@@ -0,0 +1,203 @@
1
+ import { DecoderResult } from '@lukso/transaction-decoder';
2
+
3
+ /**
4
+ * Different contexts WHERE transaction views are displayed
5
+ *
6
+ * Context determines the environment/location, which affects:
7
+ * - Available space
8
+ * - User intent
9
+ * - Security requirements
10
+ * - Interaction patterns
11
+ */
12
+ type ViewContext = 'approval' | 'feed' | 'list' | 'detail' | 'review' | 'notification' | 'embed' | 'batch-summary';
13
+ /**
14
+ * Different variants of HOW transaction views are displayed
15
+ *
16
+ * Variant determines the presentation style within a context:
17
+ * - Same transaction can have different variants in different contexts
18
+ * - Example: 'collapsed' in feed vs 'collapsed' in approval are different
19
+ */
20
+ type ViewVariant = 'full' | 'collapsed' | 'minimal' | 'icon-only' | 'compact' | 'expanded' | string;
21
+ /**
22
+ * Context-specific display requirements
23
+ */
24
+ interface ViewContextRequirements {
25
+ /** Maximum height constraint */
26
+ maxHeight?: number;
27
+ /** Whether to show action buttons */
28
+ showActions?: boolean;
29
+ /** Level of detail to display */
30
+ detailLevel: 'minimal' | 'summary' | 'full' | 'debug';
31
+ /** Whether user can expand for more details */
32
+ expandable?: boolean;
33
+ /** Color scheme preference */
34
+ colorScheme?: 'light' | 'dark' | 'auto';
35
+ /** Whether to emphasize security warnings */
36
+ emphasizeSecurity?: boolean;
37
+ }
38
+
39
+ type DecoderRecordForSelection = DecoderResult & {
40
+ recordType?: string;
41
+ functionName?: string;
42
+ contractAddress?: string;
43
+ standard?: string;
44
+ };
45
+
46
+ /**
47
+ * Criteria that can be used to match transactions to views
48
+ */
49
+ interface ViewMatchCriteria {
50
+ /** LSP standard (e.g., 'LSP7', 'LSP8', 'LSP0') */
51
+ standard?: string | string[];
52
+ /** Function name from ABI (e.g., 'transfer', 'setData', 'execute') */
53
+ functionName?: string | string[];
54
+ /** Record type from decoder (e.g., 'lsp7-transfer', 'set-data') */
55
+ recordType?: string | string[];
56
+ /** Contract address (for specific contract implementations) */
57
+ contractAddress?: string | string[];
58
+ /** Chain ID (for network-specific views) */
59
+ chainId?: number | number[];
60
+ /** Display context (opt-in) - WHERE to display (feed, approval, list, etc.) */
61
+ context?: ViewContext | ViewContext[];
62
+ /** Display variant (opt-in) - HOW to display (collapsed, minimal, full, etc.) */
63
+ variant?: ViewVariant | ViewVariant[];
64
+ /** Context requirements (opt-in) - additional constraints for context matching */
65
+ contextRequirements?: Partial<ViewContextRequirements>;
66
+ /**
67
+ * Custom matcher function for complex synchronous logic.
68
+ * Returns the number of conditions that matched (higher = better match).
69
+ *
70
+ * IMPORTANT: Must be synchronous and only use data from DecoderResult.
71
+ * For async operations, populate transaction.custom in an enhancer.
72
+ *
73
+ * @returns Number of matching conditions (0 = no match, higher = stronger match)
74
+ *
75
+ * @example
76
+ * // Match token transfers (tokenType === 0)
77
+ * customMatcher: (tx) => {
78
+ * let matches = 0
79
+ * if (tx.custom?.tokenType === 0) matches++
80
+ * if (BigInt(tx.value || 0) > 0) matches++
81
+ * return matches
82
+ * }
83
+ */
84
+ customMatcher?: (transaction: DecoderResult) => number;
85
+ }
86
+ /**
87
+ * Framework-agnostic view definition
88
+ */
89
+ interface ViewDefinition {
90
+ /** Unique identifier for this view */
91
+ id: string;
92
+ /** Human-readable name */
93
+ name: string;
94
+ /** Criteria for matching transactions to this view */
95
+ criteria: ViewMatchCriteria;
96
+ /** Priority when multiple views match (higher = preferred) */
97
+ priority: number;
98
+ /** Supported frameworks for this view */
99
+ frameworks: FrameworkSupport;
100
+ /** Optional description */
101
+ description?: string;
102
+ }
103
+ /**
104
+ * Framework-specific loading configurations
105
+ *
106
+ * Strategic Framework Selection (Suffering Economics Optimized):
107
+ * - lit: Universal web components (works in Vue, React, Angular, Svelte, etc.)
108
+ * - vue: Native Vue components (optional, for Vue-specific optimizations)
109
+ * - rn: React Native components (mobile-native, optional - falls back to WebView)
110
+ *
111
+ * Lit is the universal fallback. Vue and React Native are optional native implementations
112
+ * that get priority when available in their respective environments.
113
+ */
114
+ interface FrameworkSupport {
115
+ lit: FrameworkViewConfig;
116
+ vue?: FrameworkViewConfig;
117
+ rn?: FrameworkViewConfig;
118
+ }
119
+ /**
120
+ * Configuration for loading a view in a specific framework
121
+ */
122
+ interface FrameworkViewConfig {
123
+ /** Loading method */
124
+ loader: ViewLoader;
125
+ /** Component name/identifier */
126
+ component: string;
127
+ /** Package where the component is located */
128
+ package?: string;
129
+ }
130
+ /**
131
+ * Different ways to load a view component
132
+ *
133
+ * Loaders support both static and lazy loading:
134
+ * - Static: `path: './Component.vue'` - bundled with app
135
+ * - Lazy: `path: () => import('./Component.vue')` - loaded on demand
136
+ */
137
+ type ViewLoader = {
138
+ type: 'dynamic-import';
139
+ path: string | (() => Promise<any>);
140
+ } | {
141
+ type: 'static-import';
142
+ path: string | (() => Promise<any>);
143
+ } | {
144
+ type: 'custom-element';
145
+ tagName: string;
146
+ } | {
147
+ type: 'registry-lookup';
148
+ registryKey: string;
149
+ } | {
150
+ type: 'custom';
151
+ loader: (config: FrameworkViewConfig) => Promise<any>;
152
+ };
153
+ /**
154
+ * Result of matching a transaction against registered views
155
+ */
156
+ interface ViewMatch {
157
+ /** The view definition that matched */
158
+ view: ViewDefinition;
159
+ /** Score indicating how well this view matches (0-1) */
160
+ score: number;
161
+ /** Which criteria matched */
162
+ matchedCriteria: (keyof ViewMatchCriteria)[];
163
+ /** Framework-specific loading config */
164
+ frameworkConfig?: FrameworkViewConfig;
165
+ }
166
+ /**
167
+ * Options for view matching
168
+ */
169
+ interface ViewMatchOptions {
170
+ /** Target framework */
171
+ framework: 'lit' | 'vue' | 'rn';
172
+ /** Display context (optional) - WHERE to display (feed, approval, list, etc.) */
173
+ context?: ViewContext;
174
+ /** Display variant (optional) - HOW to display (collapsed, minimal, full, etc.) */
175
+ variant?: ViewVariant;
176
+ /** Context requirements (optional) - additional constraints for context-aware matching */
177
+ contextRequirements?: Partial<ViewContextRequirements>;
178
+ /** Minimum score threshold (0-1) */
179
+ minScore?: number;
180
+ /** Maximum number of matches to return */
181
+ maxMatches?: number;
182
+ /** Whether to include framework config in results */
183
+ includeFrameworkConfig?: boolean;
184
+ }
185
+ /**
186
+ * Registry for managing view definitions
187
+ */
188
+ interface ViewRegistry {
189
+ /** Register a new view */
190
+ register(view: ViewDefinition): void;
191
+ /** Unregister a view by ID */
192
+ unregister(viewId: string): void;
193
+ /** Get all registered views */
194
+ getAllViews(): ViewDefinition[];
195
+ /** Find best matching views for a transaction */
196
+ findMatches(transaction: DecoderResult, options: ViewMatchOptions): ViewMatch[];
197
+ /** Get a specific view by ID */
198
+ getView(viewId: string): ViewDefinition | undefined;
199
+ /** Clear all registered views */
200
+ clear(): void;
201
+ }
202
+
203
+ export type { DecoderRecordForSelection as D, FrameworkSupport as F, ViewContext as V, ViewDefinition as a, ViewMatch as b, ViewMatchCriteria as c, ViewContextRequirements as d, ViewVariant as e, FrameworkViewConfig as f, ViewLoader as g, ViewMatchOptions as h, ViewRegistry as i };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lukso/transaction-view-headless",
3
- "version": "0.4.3-dev.661418d",
3
+ "version": "0.4.3-dev.a07a66f",
4
4
  "description": "Framework-agnostic transaction decoder and view selection system",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -35,8 +35,8 @@
35
35
  "dependencies": {
36
36
  "@preact/signals-core": "^1.12.1",
37
37
  "@tanstack/query-core": "^5.90.12",
38
- "viem": "^2.43.1",
39
- "@lukso/transaction-decoder": "1.3.3-dev.661418d"
38
+ "viem": "^2.43.3",
39
+ "@lukso/transaction-decoder": "1.3.3-dev.a07a66f"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@types/node": "^25.0.3",
@@ -100,13 +100,16 @@ export interface TransactionPlaybackState {
100
100
 
101
101
  /**
102
102
  * Check if a transaction is a batch transaction
103
+ *
104
+ * Only executeBatch is a navigable batch where:
105
+ * - Index 0 shows batch summary
106
+ * - Index 1+ shows individual child transactions
107
+ *
108
+ * setDataBatch is NOT a batch - it's a single transaction with a special view
109
+ * that renders all key/value pairs from children.
103
110
  */
104
111
  function isBatchTransaction(transaction: DecoderResult): boolean {
105
- return (
106
- transaction.resultType === 'executeBatch' ||
107
- transaction.resultType === 'setDataBatch' ||
108
- !!(transaction as any).children?.length
109
- )
112
+ return transaction.resultType === 'executeBatch'
110
113
  }
111
114
 
112
115
  /**
@@ -3,6 +3,20 @@ export type {
3
3
  ViewContextRequirements,
4
4
  ViewVariant,
5
5
  } from './view-contexts'
6
+ export type {
7
+ HeaderInfoEvent,
8
+ TransactionHeaderInfo,
9
+ TransactionModification,
10
+ TransactionModificationEvent,
11
+ TransactionModificationWithContext,
12
+ } from './view-events'
13
+ export {
14
+ dispatchHeaderInfo,
15
+ dispatchTransactionModification,
16
+ isHeaderInfoEvent,
17
+ isTransactionModificationEvent,
18
+ TransactionViewEvents,
19
+ } from './view-events'
6
20
  export type {
7
21
  DecoderRecordForSelection,
8
22
  FrameworkSupport,