@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,448 @@
1
+ /**
2
+ * The "Crazy" Strategy: Lit + React Native Only
3
+ *
4
+ * Why this might actually be genius:
5
+ * - Lit Web Components work in ANY web framework (Vue, React, Svelte, etc.)
6
+ * - React Native handles the mobile-native use case
7
+ * - Only TWO implementations to maintain instead of 4+
8
+ * - Web Components are framework-agnostic by design
9
+ */
10
+
11
+ export const LitPlusRNStrategy = {
12
+ // The core insight: Web Components are truly universal
13
+ litUniversality: `
14
+ <!-- Works in vanilla HTML -->
15
+ <lsp7-transfer-view
16
+ .transaction="\${transaction}"
17
+ @approve="\${handleApprove}"
18
+ ></lsp7-transfer-view>
19
+
20
+ <!-- Works in Vue -->
21
+ <template>
22
+ <lsp7-transfer-view
23
+ :transaction="transaction"
24
+ @approve="handleApprove"
25
+ />
26
+ </template>
27
+
28
+ <!-- Works in React -->
29
+ function App() {
30
+ return (
31
+ <lsp7-transfer-view
32
+ ref={el => el.transaction = transaction}
33
+ onApprove={handleApprove}
34
+ />
35
+ )
36
+ }
37
+
38
+ <!-- Works in Svelte -->
39
+ <lsp7-transfer-view
40
+ transaction={transaction}
41
+ on:approve={handleApprove}
42
+ />
43
+
44
+ <!-- Works in Angular -->
45
+ <lsp7-transfer-view
46
+ [transaction]="transaction"
47
+ (approve)="handleApprove($event)"
48
+ ></lsp7-transfer-view>`,
49
+
50
+ // React Native stays separate (it has to)
51
+ reactNativeReality: `
52
+ // React Native - still needs its own implementation
53
+ import { View, Text, TouchableOpacity } from rn
54
+
55
+ export function LSP7Transfer({ transaction, onApprove }) {
56
+ return (
57
+ <View style={styles.container}>
58
+ <Text style={styles.amount}>
59
+ {transaction.amount} {transaction.symbol}
60
+ </Text>
61
+ <TouchableOpacity onPress={() => onApprove(transaction)}>
62
+ <Text>Approve</Text>
63
+ </TouchableOpacity>
64
+ </View>
65
+ )
66
+ }
67
+
68
+ // This can't be a web component - different runtime entirely
69
+ `,
70
+ }
71
+
72
+ /**
73
+ * Package structure: Simplified to just 2 implementations
74
+ */
75
+ export const SimplifiedPackageStructure = `
76
+ packages/
77
+ ├── decoder-headless/ # Framework-agnostic business logic ⭐
78
+ ├── decoder-web-components/ # Lit Web Components (works everywhere on web) 🌐
79
+ └── decoder-react-native/ # React Native components (mobile only) 📱
80
+
81
+ That's it! Just 3 packages instead of 5+.
82
+ `
83
+
84
+ /**
85
+ * How each web framework would use Lit components
86
+ */
87
+ export const WebFrameworkIntegration = {
88
+ vue: `
89
+ <!-- Vue: Just use the web component -->
90
+ <template>
91
+ <div class="transaction-view">
92
+ <lsp7-transfer-view
93
+ :transaction="transaction"
94
+ :show-actions="showActions"
95
+ @approve="handleApprove"
96
+ @reject="handleReject"
97
+ />
98
+ </div>
99
+ </template>
100
+
101
+ <script setup>
102
+ import '@lukso/decoder-web-components' // Registers all components
103
+
104
+ const props = defineProps(['transaction', 'showActions'])
105
+ const emit = defineEmits(['approve', 'reject'])
106
+
107
+ const handleApprove = (event) => emit('approve', event.detail)
108
+ const handleReject = (event) => emit('reject', event.detail)
109
+ </script>
110
+
111
+ <!-- Vue developers barely notice it's a web component! -->`,
112
+
113
+ react: `
114
+ // React: Use web component with proper event binding
115
+ import { useRef, useEffect } from 'react'
116
+ import '@lukso/decoder-web-components'
117
+
118
+ export function TransactionView({ transaction, showActions, onApprove, onReject }) {
119
+ const elementRef = useRef(null)
120
+
121
+ useEffect(() => {
122
+ const element = elementRef.current
123
+ if (!element) return
124
+
125
+ // Set complex properties via JS (not HTML attributes)
126
+ element.transaction = transaction
127
+ element.showActions = showActions
128
+
129
+ // Listen to custom events
130
+ const handleApprove = (e) => onApprove?.(e.detail)
131
+ const handleReject = (e) => onReject?.(e.detail)
132
+
133
+ element.addEventListener('approve', handleApprove)
134
+ element.addEventListener('reject', handleReject)
135
+
136
+ return () => {
137
+ element.removeEventListener('approve', handleApprove)
138
+ element.removeEventListener('reject', handleReject)
139
+ }
140
+ }, [transaction, showActions, onApprove, onReject])
141
+
142
+ return <lsp7-transfer-view ref={elementRef} />
143
+ }
144
+
145
+ // Or use a React wrapper library like @lit-labs/react`,
146
+
147
+ reactWithWrapper: `
148
+ // Even better: Use @lit-labs/react for automatic wrapping
149
+ import { createComponent } from '@lit-labs/react'
150
+ import { LSP7TransferView } from '@lukso/decoder-web-components'
151
+
152
+ // Automatically generates React wrapper with proper TypeScript
153
+ export const LSP7Transfer = createComponent({
154
+ tagName: 'lsp7-transfer-view',
155
+ elementClass: LSP7TransferView,
156
+ react: React,
157
+ events: {
158
+ onApprove: 'approve',
159
+ onReject: 'reject'
160
+ }
161
+ })
162
+
163
+ // Now use like a normal React component:
164
+ <LSP7Transfer
165
+ transaction={transaction}
166
+ showActions={showActions}
167
+ onApprove={handleApprove}
168
+ onReject={handleReject}
169
+ />`,
170
+
171
+ svelte: `
172
+ <!-- Svelte: Web components just work -->
173
+ <script>
174
+ import '@lukso/decoder-web-components'
175
+
176
+ export let transaction
177
+ export let showActions = false
178
+
179
+ function handleApprove(event) {
180
+ console.log('Approved:', event.detail)
181
+ }
182
+ </script>
183
+
184
+ <lsp7-transfer-view
185
+ {transaction}
186
+ {showActions}
187
+ on:approve={handleApprove}
188
+ />
189
+
190
+ <!-- Svelte has excellent web component support -->`,
191
+
192
+ angular: `
193
+ // Angular: Register web components in module
194
+ import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'
195
+ import '@lukso/decoder-web-components'
196
+
197
+ @Component({
198
+ template: \`
199
+ <lsp7-transfer-view
200
+ [transaction]="transaction"
201
+ [showActions]="showActions"
202
+ (approve)="handleApprove($event)"
203
+ (reject)="handleReject($event)"
204
+ ></lsp7-transfer-view>
205
+ \`,
206
+ schemas: [CUSTOM_ELEMENTS_SCHEMA]
207
+ })
208
+ export class TransactionComponent {
209
+ // Angular treats web components as first-class citizens
210
+ }`,
211
+ }
212
+
213
+ /**
214
+ * The Lit implementation - write once, run everywhere (on web)
215
+ */
216
+ export const LitImplementation = `
217
+ // lsp7-transfer-view.ts - The ONE web implementation
218
+ import { LitElement, html, css } from 'lit'
219
+ import { customElement, property, state } from 'lit/decorators.js'
220
+ import { useTransactionView } from '@lukso/transaction-view-headless'
221
+
222
+ @customElement('lsp7-transfer-view')
223
+ export class LSP7TransferView extends LitElement {
224
+ @property({ type: Object }) transaction = null
225
+ @property({ type: Boolean }) showActions = false
226
+ @property({ type: String }) context = 'detail'
227
+
228
+ @state() private addressData = {}
229
+ @state() private isLoading = true
230
+ @state() private formatAmount = (x) => x
231
+
232
+ override async connectedCallback() {
233
+ super.connectedCallback()
234
+
235
+ if (this.transaction) {
236
+ await this.loadTransactionData()
237
+ }
238
+ }
239
+
240
+ override async updated(changedProperties) {
241
+ if (changedProperties.has('transaction') && this.transaction) {
242
+ await this.loadTransactionData()
243
+ }
244
+ }
245
+
246
+ private async loadTransactionData() {
247
+ this.isLoading = true
248
+
249
+ try {
250
+ const viewData = await useTransactionView(this.transaction, {
251
+ framework: 'lit',
252
+ context: this.context
253
+ })
254
+
255
+ this.addressData = viewData.addressData
256
+ this.formatAmount = viewData.formatAmount
257
+ } finally {
258
+ this.isLoading = false
259
+ }
260
+ }
261
+
262
+ override render() {
263
+ if (this.isLoading) {
264
+ return html\`<div class="loading">Loading transaction...</div>\`
265
+ }
266
+
267
+ return html\`
268
+ <div class="lsp7-transfer">
269
+ <div class="transfer-flow">
270
+ <address-display
271
+ .address=\${this.transaction.from}
272
+ .resolved=\${this.addressData[this.transaction.from]}
273
+ @click=\${this._onAddressClick}
274
+ ></address-display>
275
+
276
+ <div class="arrow">→</div>
277
+
278
+ <address-display
279
+ .address=\${this.transaction.to}
280
+ .resolved=\${this.addressData[this.transaction.to]}
281
+ ></address-display>
282
+ </div>
283
+
284
+ <div class="amount">
285
+ \${this.formatAmount(this.transaction.amount)} \${this.transaction.symbol}
286
+ </div>
287
+
288
+ \${this.showActions ? html\`
289
+ <div class="actions">
290
+ <button @click=\${this._onReject} class="reject-btn">
291
+ Reject
292
+ </button>
293
+ <button @click=\${this._onApprove} class="approve-btn">
294
+ Approve
295
+ </button>
296
+ </div>
297
+ \` : ''}
298
+ </div>
299
+ \`
300
+ }
301
+
302
+ static styles = css\`
303
+ :host {
304
+ display: block;
305
+ padding: 16px;
306
+ border: 1px solid #e0e0e0;
307
+ border-radius: 8px;
308
+ }
309
+
310
+ .transfer-flow {
311
+ display: flex;
312
+ align-items: center;
313
+ gap: 12px;
314
+ margin-bottom: 12px;
315
+ }
316
+
317
+ .amount {
318
+ font-size: 18px;
319
+ font-weight: bold;
320
+ margin-bottom: 16px;
321
+ }
322
+
323
+ .actions {
324
+ display: flex;
325
+ gap: 12px;
326
+ }
327
+
328
+ button {
329
+ padding: 8px 16px;
330
+ border: none;
331
+ border-radius: 4px;
332
+ cursor: pointer;
333
+ }
334
+
335
+ .approve-btn {
336
+ background: #4caf50;
337
+ color: white;
338
+ }
339
+
340
+ .reject-btn {
341
+ background: #f44336;
342
+ color: white;
343
+ }
344
+ \`
345
+
346
+ private _onApprove() {
347
+ this.dispatchEvent(new CustomEvent('approve', {
348
+ detail: this.transaction,
349
+ bubbles: true
350
+ }))
351
+ }
352
+
353
+ private _onReject() {
354
+ this.dispatchEvent(new CustomEvent('reject', {
355
+ detail: this.transaction,
356
+ bubbles: true
357
+ }))
358
+ }
359
+
360
+ private _onAddressClick(event) {
361
+ this.dispatchEvent(new CustomEvent('address-click', {
362
+ detail: event.detail,
363
+ bubbles: true
364
+ }))
365
+ }
366
+ }`
367
+
368
+ /**
369
+ * Benefits of this "crazy" approach
370
+ */
371
+ export const Benefits = [
372
+ '✅ Write web UI once, works in ALL web frameworks',
373
+ '✅ Only 2 implementations to maintain (Lit + RN)',
374
+ '✅ Future-proof - new web frameworks automatically supported',
375
+ '✅ Better performance - native web components',
376
+ '✅ No framework lock-in for web usage',
377
+ '✅ All business logic still shared via headless',
378
+ '✅ Shadow DOM provides true style encapsulation',
379
+ '✅ Can be used in micro-frontends easily',
380
+ ]
381
+
382
+ /**
383
+ * Potential concerns and solutions
384
+ */
385
+ export const ConcernsAndSolutions = {
386
+ concern1: {
387
+ issue: 'React developers might not like web components',
388
+ solution: `Use @lit-labs/react for seamless React integration:
389
+
390
+ import { LSP7Transfer } from '@lukso/decoder-react-wrappers'
391
+
392
+ // Feels like a normal React component
393
+ <LSP7Transfer transaction={tx} onApprove={handleApprove} />`,
394
+ },
395
+
396
+ concern2: {
397
+ issue: 'TypeScript integration might be tricky',
398
+ solution: `Generate TypeScript declarations for all web components:
399
+
400
+ // Generated types
401
+ declare global {
402
+ namespace JSX {
403
+ interface IntrinsicElements {
404
+ 'lsp7-transfer-view': LSP7TransferViewProps
405
+ }
406
+ }
407
+ }`,
408
+ },
409
+
410
+ concern3: {
411
+ issue: 'Bundle size concerns',
412
+ solution: `Tree shake unused components:
413
+
414
+ // Only import what you need
415
+ import '@lukso/decoder-web-components/lsp7-transfer-view'
416
+
417
+ // Not the entire component library`,
418
+ },
419
+
420
+ concern4: {
421
+ issue: 'Framework-specific styling integration',
422
+ solution: `CSS custom properties for theming:
423
+
424
+ lsp7-transfer-view {
425
+ --primary-color: var(--vue-primary, #42b883);
426
+ --border-radius: var(--app-border-radius, 8px);
427
+ }`,
428
+ },
429
+ }
430
+
431
+ export const Conclusion = `
432
+ 🤯 This "crazy" idea might actually be GENIUS:
433
+
434
+ Instead of maintaining 4+ framework implementations:
435
+ - ✅ 1 Lit implementation (works in Vue, React, Svelte, Angular, vanilla)
436
+ - ✅ 1 React Native implementation (mobile)
437
+ - ✅ 1 headless system (shared business logic)
438
+
439
+ Total: 3 packages instead of 5+
440
+
441
+ The web components approach gives you TRUE framework universality,
442
+ not the fake kind where you're fighting against each framework's quirks.
443
+
444
+ And React Native gets its own native-optimized implementation because
445
+ mobile deserves better than web-in-a-box.
446
+
447
+ This might be the perfect balance of code reuse and platform optimization! 🎯
448
+ `
@@ -0,0 +1,174 @@
1
+ import { LoaderHelpers } from '../registry/view-loader'
2
+ import type { ViewDefinition } from '../types/view-matching'
3
+
4
+ /**
5
+ * Example view definitions demonstrating custom matcher usage for LSP7 tokens.
6
+ * These examples show how to distinguish between different LSP7 token types
7
+ * (Token vs NFT vs Collection) using the result.custom metadata populated
8
+ * by the LSP7 enhancer.
9
+ */
10
+
11
+ /**
12
+ * View for LSP7 Token transfers (tokenType === 0)
13
+ * Displays token-specific UI with amount, balance, etc.
14
+ */
15
+ export const LSP7TokenTransferView: ViewDefinition = {
16
+ id: 'lsp7-token-transfer',
17
+ name: 'LSP7 Token Transfer',
18
+ description: 'Optimized view for fungible LSP7 token transfers',
19
+ priority: 100,
20
+ criteria: {
21
+ standard: 'LSP7',
22
+ functionName: 'transfer',
23
+ customMatcher: (tx) => {
24
+ let matches = 0
25
+ // Check if it's a token (tokenType === 0)
26
+ if (tx.custom?.tokenType === 0) matches++
27
+ if (tx.custom?.isToken === true) matches++
28
+ return matches
29
+ },
30
+ },
31
+ frameworks: {
32
+ lit: {
33
+ loader: LoaderHelpers.litComponent('lsp7-token-transfer-view'),
34
+ component: 'lsp7-token-transfer-view',
35
+ package: '@lukso/transaction-view-components',
36
+ },
37
+ },
38
+ }
39
+
40
+ /**
41
+ * View for LSP7 NFT transfers (tokenType === 1)
42
+ * Displays NFT-specific UI with collectible metadata
43
+ */
44
+ export const LSP7NFTTransferView: ViewDefinition = {
45
+ id: 'lsp7-nft-transfer',
46
+ name: 'LSP7 NFT Transfer',
47
+ description: 'Optimized view for LSP7 NFT/collectible transfers',
48
+ priority: 100,
49
+ criteria: {
50
+ standard: 'LSP7',
51
+ functionName: 'transfer',
52
+ customMatcher: (tx) => {
53
+ let matches = 0
54
+ // Check if it's an NFT (tokenType === 1)
55
+ if (tx.custom?.tokenType === 1) matches++
56
+ if (tx.custom?.isNFT === true) matches++
57
+ return matches
58
+ },
59
+ },
60
+ frameworks: {
61
+ lit: {
62
+ loader: LoaderHelpers.litComponent('lsp7-nft-transfer-view'),
63
+ component: 'lsp7-nft-transfer-view',
64
+ package: '@lukso/transaction-view-components',
65
+ },
66
+ },
67
+ }
68
+
69
+ /**
70
+ * View for LSP7 Collection transfers (tokenType === 2)
71
+ * Displays collection-specific UI
72
+ */
73
+ export const LSP7CollectionTransferView: ViewDefinition = {
74
+ id: 'lsp7-collection-transfer',
75
+ name: 'LSP7 Collection Transfer',
76
+ description: 'Optimized view for LSP7 collection transfers',
77
+ priority: 100,
78
+ criteria: {
79
+ standard: 'LSP7',
80
+ functionName: 'transfer',
81
+ customMatcher: (tx) => {
82
+ let matches = 0
83
+ // Check if it's a collection (tokenType === 2)
84
+ if (tx.custom?.tokenType === 2) matches++
85
+ if (tx.custom?.isCollection === true) matches++
86
+ return matches
87
+ },
88
+ },
89
+ frameworks: {
90
+ lit: {
91
+ loader: LoaderHelpers.litComponent('lsp7-collection-transfer-view'),
92
+ component: 'lsp7-collection-transfer-view',
93
+ package: '@lukso/transaction-view-components',
94
+ },
95
+ },
96
+ }
97
+
98
+ /**
99
+ * Generic fallback view for LSP7 transfers without metadata
100
+ * This will match when the custom metadata is not available or
101
+ * when none of the specific views match.
102
+ */
103
+ export const LSP7GenericTransferView: ViewDefinition = {
104
+ id: 'lsp7-generic-transfer',
105
+ name: 'LSP7 Transfer',
106
+ description: 'Generic view for LSP7 transfers (fallback)',
107
+ priority: 50, // Lower priority than specific views
108
+ criteria: {
109
+ standard: 'LSP7',
110
+ functionName: 'transfer',
111
+ // No customMatcher - matches all LSP7 transfers regardless of metadata
112
+ },
113
+ frameworks: {
114
+ lit: {
115
+ loader: LoaderHelpers.litComponent('lsp7-transfer-view'),
116
+ component: 'lsp7-transfer-view',
117
+ package: '@lukso/transaction-view-components',
118
+ },
119
+ },
120
+ }
121
+
122
+ /**
123
+ * Example of combining multiple criteria with custom matching
124
+ * This view matches large token transfers (> 1000 units) to a specific contract
125
+ */
126
+ export const LSP7LargeTokenTransferView: ViewDefinition = {
127
+ id: 'lsp7-large-token-transfer',
128
+ name: 'LSP7 Large Token Transfer',
129
+ description: 'Special view for large token transfers',
130
+ priority: 150, // Higher priority than generic token transfer view
131
+ criteria: {
132
+ standard: 'LSP7',
133
+ functionName: 'transfer',
134
+ customMatcher: (tx) => {
135
+ let matches = 0
136
+
137
+ // Must be a token
138
+ if (tx.custom?.isToken === true) matches++
139
+
140
+ // Check if transfer amount is large (> 1000 tokens)
141
+ // Assuming amount is stored in args[2] or a specific field
142
+ const amount = tx.args?.[2]?.value as bigint | undefined
143
+ if (amount && amount > BigInt('1000000000000000000000')) {
144
+ // > 1000 tokens (18 decimals)
145
+ matches++
146
+ }
147
+
148
+ // Additional criteria can be added
149
+ if (tx.value && BigInt(tx.value) > 0) {
150
+ matches++ // Has native token value attached
151
+ }
152
+
153
+ return matches
154
+ },
155
+ },
156
+ frameworks: {
157
+ lit: {
158
+ loader: LoaderHelpers.litComponent('lsp7-large-transfer-view'),
159
+ component: 'lsp7-large-transfer-view',
160
+ package: '@lukso/transaction-view-components',
161
+ },
162
+ },
163
+ }
164
+
165
+ /**
166
+ * All LSP7 custom matcher examples
167
+ */
168
+ export const LSP7CustomMatcherExamples: ViewDefinition[] = [
169
+ LSP7TokenTransferView,
170
+ LSP7NFTTransferView,
171
+ LSP7CollectionTransferView,
172
+ LSP7GenericTransferView,
173
+ LSP7LargeTokenTransferView,
174
+ ]