@lukso/transaction-view-headless 0.2.2-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 (76) hide show
  1. package/.turbo/turbo-build.log +51 -0
  2. package/CHANGELOG.md +88 -0
  3. package/COMPONENT_ARCHITECTURE.md +190 -0
  4. package/COMPONENT_CONVERSION_ANALYSIS.md +371 -0
  5. package/CONTEXT_VARIANT_GUIDE.md +425 -0
  6. package/LAZY_LOADING_GUIDE.md +534 -0
  7. package/LICENSE +201 -0
  8. package/PLAYBACK_EXAMPLES.md +658 -0
  9. package/PLAYBACK_GUIDE.md +402 -0
  10. package/README.md +43 -0
  11. package/REGISTRY_SUMMARY.md +638 -0
  12. package/SUFFERING_ECONOMICS.md +346 -0
  13. package/SUFFERING_ECONOMICS.zip +0 -0
  14. package/VIEW_REGISTRATION_GUIDE.md +795 -0
  15. package/dist/composables/index.cjs +1321 -0
  16. package/dist/composables/index.cjs.map +1 -0
  17. package/dist/composables/index.d.cts +6 -0
  18. package/dist/composables/index.d.ts +6 -0
  19. package/dist/composables/index.js +1276 -0
  20. package/dist/composables/index.js.map +1 -0
  21. package/dist/index-CMLU1hKL.d.ts +374 -0
  22. package/dist/index-CSDjhiKV.d.cts +374 -0
  23. package/dist/index.cjs +1534 -0
  24. package/dist/index.cjs.map +1 -0
  25. package/dist/index.d.cts +93 -0
  26. package/dist/index.d.ts +93 -0
  27. package/dist/index.js +1463 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/registry/index.cjs +522 -0
  30. package/dist/registry/index.cjs.map +1 -0
  31. package/dist/registry/index.d.cts +46 -0
  32. package/dist/registry/index.d.ts +46 -0
  33. package/dist/registry/index.js +487 -0
  34. package/dist/registry/index.js.map +1 -0
  35. package/dist/types/index.cjs +19 -0
  36. package/dist/types/index.cjs.map +1 -0
  37. package/dist/types/index.d.cts +203 -0
  38. package/dist/types/index.d.ts +203 -0
  39. package/dist/types/index.js +1 -0
  40. package/dist/types/index.js.map +1 -0
  41. package/dist/utils/index.cjs +217 -0
  42. package/dist/utils/index.cjs.map +1 -0
  43. package/dist/utils/index.d.cts +47 -0
  44. package/dist/utils/index.d.ts +47 -0
  45. package/dist/utils/index.js +188 -0
  46. package/dist/utils/index.js.map +1 -0
  47. package/dist/view-loader-dD86QAlQ.d.cts +121 -0
  48. package/dist/view-loader-ii8AxiQR.d.ts +121 -0
  49. package/package.json +64 -0
  50. package/publish.log +0 -0
  51. package/src/composables/index.ts +59 -0
  52. package/src/composables/use-image-loader.ts +315 -0
  53. package/src/composables/use-transaction-playback.ts +396 -0
  54. package/src/composables/use-transaction-view.ts +309 -0
  55. package/src/config/lukso-config.ts +171 -0
  56. package/src/examples/context-aware-views.ts +300 -0
  57. package/src/examples/example-views.ts +197 -0
  58. package/src/examples/lit-plus-rn-strategy.ts +448 -0
  59. package/src/examples/lsp7-custom-matcher-examples.ts +174 -0
  60. package/src/examples/opt-in-context-examples.ts +372 -0
  61. package/src/examples/optimized-view-definitions.ts +408 -0
  62. package/src/examples/vue-to-lit-compilation.ts +358 -0
  63. package/src/hooks/useAddressQuery.ts +135 -0
  64. package/src/hooks/useAddressResolution.ts +437 -0
  65. package/src/index.ts +36 -0
  66. package/src/registry/index.ts +13 -0
  67. package/src/registry/view-loader.ts +305 -0
  68. package/src/registry/view-registry.ts +135 -0
  69. package/src/types/index.ts +16 -0
  70. package/src/types/view-contexts.ts +72 -0
  71. package/src/types/view-matching.ts +173 -0
  72. package/src/utils/context-matcher.ts +165 -0
  73. package/src/utils/index.ts +5 -0
  74. package/src/utils/view-matcher.ts +338 -0
  75. package/tsconfig.json +20 -0
  76. package/tsup.config.ts +34 -0
@@ -0,0 +1,425 @@
1
+ # Context and Variant Guide
2
+
3
+ This guide explains how to use **Context** and **Variant** to register and match transaction views for different display scenarios.
4
+
5
+ ## Core Concepts
6
+
7
+ ### Context: WHERE to Display
8
+
9
+ **Context** defines WHERE a transaction view is being displayed, which affects the environment, user intent, and interaction patterns.
10
+
11
+ Available contexts:
12
+ - `approval` - Transaction approval flow (security-focused)
13
+ - `feed` - Activity feed (compact summaries)
14
+ - `list` - Transaction lists (scannable format)
15
+ - `detail` - Full transaction detail (comprehensive)
16
+ - `review` - Pre-submission review (verification-focused)
17
+ - `notification` - Push notifications (minimal info)
18
+ - `embed` - Embedded in other interfaces
19
+ - `batch-summary` - Inside a batch summary display
20
+
21
+ ### Variant: HOW to Display
22
+
23
+ **Variant** defines HOW a transaction view should be rendered within a given context.
24
+
25
+ Available variants:
26
+ - `full` - Complete detailed view
27
+ - `collapsed` - Collapsed/summary view
28
+ - `minimal` - Minimal information only
29
+ - `icon-only` - Just icon/avatar
30
+ - `compact` - Compact single-line format
31
+ - `expanded` - Expanded with all details
32
+ - Custom strings allowed
33
+
34
+ ## Why Separate Context and Variant?
35
+
36
+ The same variant can mean different things in different contexts:
37
+
38
+ ```typescript
39
+ // "collapsed" in feed - might show "3 transfers"
40
+ context: 'feed', variant: 'collapsed'
41
+
42
+ // "collapsed" in approval - still shows critical security info
43
+ context: 'approval', variant: 'collapsed'
44
+
45
+ // "collapsed" in batch-summary - might skip unimportant transactions
46
+ context: 'batch-summary', variant: 'collapsed'
47
+ ```
48
+
49
+ ## Registering Views
50
+
51
+ ### Single Context and Variant
52
+
53
+ ```typescript
54
+ registry.register({
55
+ id: 'lsp7-transfer-feed-collapsed',
56
+ name: 'LSP7 Transfer (Feed Collapsed)',
57
+ criteria: {
58
+ standard: 'LSP7',
59
+ functionName: 'transfer',
60
+ context: 'feed', // Only matches feed
61
+ variant: 'collapsed', // Only matches collapsed
62
+ },
63
+ priority: 100,
64
+ frameworks: {
65
+ lit: {
66
+ loader: { type: 'dynamic-import', path: () => import('./LSP7TransferCollapsed.lit') },
67
+ component: 'lsp7-transfer-collapsed',
68
+ },
69
+ },
70
+ })
71
+ ```
72
+
73
+ ### Multiple Contexts
74
+
75
+ ```typescript
76
+ registry.register({
77
+ id: 'lsp7-transfer-compact',
78
+ name: 'LSP7 Transfer (Compact)',
79
+ criteria: {
80
+ standard: 'LSP7',
81
+ functionName: 'transfer',
82
+ context: ['feed', 'list'], // Matches both feed and list
83
+ variant: 'compact',
84
+ },
85
+ priority: 90,
86
+ frameworks: { /* ... */ },
87
+ })
88
+ ```
89
+
90
+ ### Universal View (No Context/Variant)
91
+
92
+ ```typescript
93
+ registry.register({
94
+ id: 'lsp7-transfer-universal',
95
+ name: 'LSP7 Transfer (Universal)',
96
+ criteria: {
97
+ standard: 'LSP7',
98
+ functionName: 'transfer',
99
+ // No context or variant = matches any context/variant
100
+ },
101
+ priority: 50, // Lower priority as fallback
102
+ frameworks: { /* ... */ },
103
+ })
104
+ ```
105
+
106
+ ## Matching Views
107
+
108
+ ### Basic Matching
109
+
110
+ ```typescript
111
+ // Find views for a transaction in feed context with collapsed variant
112
+ const matches = registry.findMatches(transaction, {
113
+ framework: 'lit',
114
+ context: 'feed',
115
+ variant: 'collapsed',
116
+ })
117
+ ```
118
+
119
+ ### Variant is Optional
120
+
121
+ ```typescript
122
+ // Without variant - matches views without variant requirement
123
+ const matches = registry.findMatches(transaction, {
124
+ framework: 'lit',
125
+ context: 'approval', // Just context, no variant
126
+ })
127
+ ```
128
+
129
+ ## Scoring
130
+
131
+ Views are scored based on how well they match:
132
+
133
+ | Criteria | Weight |
134
+ |----------|--------|
135
+ | recordType | 0.20 |
136
+ | context | 0.15 |
137
+ | variant | 0.15 |
138
+ | customMatcher | 0.15 |
139
+ | functionName | 0.12 |
140
+ | standard | 0.10 |
141
+ | contractAddress | 0.08 |
142
+ | contextRequirements | 0.03 |
143
+ | chainId | 0.02 |
144
+
145
+ **Example:**
146
+ ```typescript
147
+ // View A: context='feed', variant='collapsed' (exact matches)
148
+ // Score: 0.15 + 0.15 = 0.30
149
+
150
+ // View B: no context/variant specified (universal fallback)
151
+ // Score: 0.00 (matches but scores lower)
152
+
153
+ // Result: View A wins!
154
+ ```
155
+
156
+ ## Custom Matchers
157
+
158
+ For complex matching logic, use `customMatcher` (weighted equally to context/variant at 0.15):
159
+
160
+ ### Example: LSP7 Decimals Check
161
+
162
+ LSP7 tokens with `decimals() == 0` are NFT-like and should display differently than fungible tokens:
163
+
164
+ ```typescript
165
+ // NFT-like LSP7 (decimals = 0)
166
+ registry.register({
167
+ id: 'lsp7-nft-transfer',
168
+ name: 'LSP7 NFT Transfer',
169
+ criteria: {
170
+ standard: 'LSP7',
171
+ functionName: 'transfer',
172
+ customMatcher: (tx) => {
173
+ // Check if this LSP7 has decimals = 0 (NFT-like)
174
+ const decimals = tx.enhancedInfo?.decimals
175
+ return decimals === 0 || decimals === '0'
176
+ },
177
+ },
178
+ priority: 100,
179
+ frameworks: {
180
+ lit: {
181
+ loader: { type: 'dynamic-import', path: () => import('./LSP7NFTTransfer.lit') },
182
+ component: 'lsp7-nft-transfer',
183
+ },
184
+ },
185
+ })
186
+
187
+ // Fungible LSP7 (decimals > 0)
188
+ registry.register({
189
+ id: 'lsp7-token-transfer',
190
+ name: 'LSP7 Token Transfer',
191
+ criteria: {
192
+ standard: 'LSP7',
193
+ functionName: 'transfer',
194
+ customMatcher: (tx) => {
195
+ // Check if this LSP7 has decimals > 0 (fungible)
196
+ const decimals = tx.enhancedInfo?.decimals
197
+ return decimals !== undefined && decimals !== 0 && decimals !== '0'
198
+ },
199
+ },
200
+ priority: 100,
201
+ frameworks: {
202
+ lit: {
203
+ loader: { type: 'dynamic-import', path: () => import('./LSP7TokenTransfer.lit') },
204
+ component: 'lsp7-token-transfer',
205
+ },
206
+ },
207
+ })
208
+
209
+ // Universal fallback (no customMatcher)
210
+ registry.register({
211
+ id: 'lsp7-transfer-fallback',
212
+ criteria: {
213
+ standard: 'LSP7',
214
+ functionName: 'transfer',
215
+ // No customMatcher = matches any LSP7 transfer
216
+ },
217
+ priority: 50, // Lower priority
218
+ frameworks: { /* ... */ },
219
+ })
220
+ ```
221
+
222
+ ### Other customMatcher Use Cases
223
+
224
+ ```typescript
225
+ // Check transaction value
226
+ customMatcher: (tx) => BigInt(tx.value || '0') > BigInt('1000000000000000000') // > 1 ETH
227
+
228
+ // Check specific parameter
229
+ customMatcher: (tx) => {
230
+ const amount = tx.namedArgs?.find(arg => arg.name === 'amount')
231
+ return amount && BigInt(amount.value) > BigInt('1000000')
232
+ }
233
+
234
+ // Check array length
235
+ customMatcher: (tx) => {
236
+ const recipients = tx.namedArgs?.find(arg => arg.name === 'recipients')
237
+ return recipients && Array.isArray(recipients.value) && recipients.value.length > 5
238
+ }
239
+
240
+ // Complex logic
241
+ customMatcher: (tx) => {
242
+ const isHighValue = BigInt(tx.value || '0') > BigInt('1000000000000000000')
243
+ const isKnownAddress = KNOWN_ADDRESSES.includes(tx.to)
244
+ return isHighValue && isKnownAddress
245
+ }
246
+ ```
247
+
248
+ ## Common Patterns
249
+
250
+ ### Pattern 1: Batch Summary with Collapsed Children
251
+
252
+ ```typescript
253
+ // Register a collapsed view for batch summaries
254
+ registry.register({
255
+ id: 'approve-collapsed-batch',
256
+ criteria: {
257
+ standard: 'LSP7',
258
+ context: 'batch-summary',
259
+ variant: 'collapsed',
260
+ },
261
+ // ...
262
+ })
263
+
264
+ // Use it
265
+ const matches = registry.findMatches(childTransaction, {
266
+ framework: 'lit',
267
+ context: 'batch-summary',
268
+ variant: 'collapsed',
269
+ })
270
+ ```
271
+
272
+ ### Pattern 2: Context-Specific Full Views
273
+
274
+ ```typescript
275
+ // Approval needs full security details
276
+ registry.register({
277
+ id: 'approve-full',
278
+ criteria: {
279
+ context: 'approval',
280
+ variant: 'full',
281
+ },
282
+ // ...
283
+ })
284
+
285
+ // Feed needs compact summaries
286
+ registry.register({
287
+ id: 'feed-compact',
288
+ criteria: {
289
+ context: 'feed',
290
+ variant: 'compact',
291
+ },
292
+ // ...
293
+ })
294
+ ```
295
+
296
+ ### Pattern 3: Fallback Chain
297
+
298
+ ```typescript
299
+ // Most specific (high priority)
300
+ registry.register({
301
+ id: 'specific',
302
+ criteria: {
303
+ standard: 'LSP7',
304
+ context: 'feed',
305
+ variant: 'collapsed',
306
+ },
307
+ priority: 100,
308
+ })
309
+
310
+ // Less specific (medium priority)
311
+ registry.register({
312
+ id: 'generic-feed',
313
+ criteria: {
314
+ standard: 'LSP7',
315
+ context: 'feed',
316
+ },
317
+ priority: 75,
318
+ })
319
+
320
+ // Universal fallback (low priority)
321
+ registry.register({
322
+ id: 'universal',
323
+ criteria: {
324
+ standard: 'LSP7',
325
+ },
326
+ priority: 50,
327
+ })
328
+ ```
329
+
330
+ ## Real-World Example: LSP7 Transfer
331
+
332
+ ```typescript
333
+ // 1. Feed - collapsed (show "Transfer 100 tokens")
334
+ registry.register({
335
+ id: 'lsp7-transfer-feed-collapsed',
336
+ criteria: {
337
+ standard: 'LSP7',
338
+ functionName: 'transfer',
339
+ context: 'feed',
340
+ variant: 'collapsed',
341
+ },
342
+ priority: 100,
343
+ frameworks: {
344
+ lit: {
345
+ loader: { type: 'dynamic-import', path: () => import('./FeedCollapsed.lit') },
346
+ component: 'lsp7-transfer-feed-collapsed',
347
+ },
348
+ },
349
+ })
350
+
351
+ // 2. Approval - full (show all security details)
352
+ registry.register({
353
+ id: 'lsp7-transfer-approval-full',
354
+ criteria: {
355
+ standard: 'LSP7',
356
+ functionName: 'transfer',
357
+ context: 'approval',
358
+ variant: 'full',
359
+ },
360
+ priority: 100,
361
+ frameworks: {
362
+ lit: {
363
+ loader: { type: 'dynamic-import', path: () => import('./ApprovalFull.lit') },
364
+ component: 'lsp7-transfer-approval-full',
365
+ },
366
+ },
367
+ })
368
+
369
+ // 3. Batch summary - minimal (show icon + amount)
370
+ registry.register({
371
+ id: 'lsp7-transfer-batch-minimal',
372
+ criteria: {
373
+ standard: 'LSP7',
374
+ functionName: 'transfer',
375
+ context: 'batch-summary',
376
+ variant: 'minimal',
377
+ },
378
+ priority: 100,
379
+ frameworks: {
380
+ lit: {
381
+ loader: { type: 'dynamic-import', path: () => import('./BatchMinimal.lit') },
382
+ component: 'lsp7-transfer-batch-minimal',
383
+ },
384
+ },
385
+ })
386
+
387
+ // 4. Universal fallback
388
+ registry.register({
389
+ id: 'lsp7-transfer-universal',
390
+ criteria: {
391
+ standard: 'LSP7',
392
+ functionName: 'transfer',
393
+ // No context/variant
394
+ },
395
+ priority: 50,
396
+ frameworks: {
397
+ lit: {
398
+ loader: { type: 'dynamic-import', path: () => import('./Universal.lit') },
399
+ component: 'lsp7-transfer',
400
+ },
401
+ },
402
+ })
403
+ ```
404
+
405
+ ## Best Practices
406
+
407
+ 1. **Always provide a universal fallback** - Register a view without context/variant constraints
408
+ 2. **Use specific contexts** - Don't overuse `embed`, be specific about WHERE
409
+ 3. **Variant is optional** - Only specify variant when you have multiple display modes
410
+ 4. **Higher priority for specific views** - More specific views should have higher priority
411
+ 5. **Test fallback chains** - Ensure there's always a view that matches
412
+
413
+ ## Testing
414
+
415
+ ```typescript
416
+ // Test that your view matches the expected context/variant
417
+ const matches = registry.findMatches(mockTransaction, {
418
+ framework: 'lit',
419
+ context: 'feed',
420
+ variant: 'collapsed',
421
+ })
422
+
423
+ expect(matches[0].view.id).toBe('lsp7-transfer-feed-collapsed')
424
+ expect(matches[0].score).toBeGreaterThan(0.8)
425
+ ```