@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.
- package/.turbo/turbo-build.log +51 -0
- package/CHANGELOG.md +88 -0
- package/COMPONENT_ARCHITECTURE.md +190 -0
- package/COMPONENT_CONVERSION_ANALYSIS.md +371 -0
- package/CONTEXT_VARIANT_GUIDE.md +425 -0
- package/LAZY_LOADING_GUIDE.md +534 -0
- package/LICENSE +201 -0
- package/PLAYBACK_EXAMPLES.md +658 -0
- package/PLAYBACK_GUIDE.md +402 -0
- package/README.md +43 -0
- package/REGISTRY_SUMMARY.md +638 -0
- package/SUFFERING_ECONOMICS.md +346 -0
- package/SUFFERING_ECONOMICS.zip +0 -0
- package/VIEW_REGISTRATION_GUIDE.md +795 -0
- package/dist/composables/index.cjs +1321 -0
- package/dist/composables/index.cjs.map +1 -0
- package/dist/composables/index.d.cts +6 -0
- package/dist/composables/index.d.ts +6 -0
- package/dist/composables/index.js +1276 -0
- package/dist/composables/index.js.map +1 -0
- package/dist/index-CMLU1hKL.d.ts +374 -0
- package/dist/index-CSDjhiKV.d.cts +374 -0
- package/dist/index.cjs +1534 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +93 -0
- package/dist/index.d.ts +93 -0
- package/dist/index.js +1463 -0
- package/dist/index.js.map +1 -0
- package/dist/registry/index.cjs +522 -0
- package/dist/registry/index.cjs.map +1 -0
- package/dist/registry/index.d.cts +46 -0
- package/dist/registry/index.d.ts +46 -0
- package/dist/registry/index.js +487 -0
- package/dist/registry/index.js.map +1 -0
- package/dist/types/index.cjs +19 -0
- package/dist/types/index.cjs.map +1 -0
- package/dist/types/index.d.cts +203 -0
- package/dist/types/index.d.ts +203 -0
- package/dist/types/index.js +1 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/index.cjs +217 -0
- package/dist/utils/index.cjs.map +1 -0
- package/dist/utils/index.d.cts +47 -0
- package/dist/utils/index.d.ts +47 -0
- package/dist/utils/index.js +188 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/view-loader-dD86QAlQ.d.cts +121 -0
- package/dist/view-loader-ii8AxiQR.d.ts +121 -0
- package/package.json +64 -0
- package/publish.log +0 -0
- package/src/composables/index.ts +59 -0
- package/src/composables/use-image-loader.ts +315 -0
- package/src/composables/use-transaction-playback.ts +396 -0
- package/src/composables/use-transaction-view.ts +309 -0
- package/src/config/lukso-config.ts +171 -0
- package/src/examples/context-aware-views.ts +300 -0
- package/src/examples/example-views.ts +197 -0
- package/src/examples/lit-plus-rn-strategy.ts +448 -0
- package/src/examples/lsp7-custom-matcher-examples.ts +174 -0
- package/src/examples/opt-in-context-examples.ts +372 -0
- package/src/examples/optimized-view-definitions.ts +408 -0
- package/src/examples/vue-to-lit-compilation.ts +358 -0
- package/src/hooks/useAddressQuery.ts +135 -0
- package/src/hooks/useAddressResolution.ts +437 -0
- package/src/index.ts +36 -0
- package/src/registry/index.ts +13 -0
- package/src/registry/view-loader.ts +305 -0
- package/src/registry/view-registry.ts +135 -0
- package/src/types/index.ts +16 -0
- package/src/types/view-contexts.ts +72 -0
- package/src/types/view-matching.ts +173 -0
- package/src/utils/context-matcher.ts +165 -0
- package/src/utils/index.ts +5 -0
- package/src/utils/view-matcher.ts +338 -0
- package/tsconfig.json +20 -0
- package/tsup.config.ts +34 -0
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* "Let the developers suffer" - The Compilation Escape Hatch 😈
|
|
3
|
+
*
|
|
4
|
+
* If developers really complain about writing Lit components,
|
|
5
|
+
* we can let them write Vue/React and compile to Lit!
|
|
6
|
+
*
|
|
7
|
+
* This gives us the best of both worlds:
|
|
8
|
+
* - Developers get to write in their preferred framework
|
|
9
|
+
* - End users get universal web components
|
|
10
|
+
* - We still only ship ONE implementation per component
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
export const VueToLitCompilation = {
|
|
14
|
+
// Developer writes Vue (comfortable)
|
|
15
|
+
source: `
|
|
16
|
+
<!-- LSP7Transfer.vue - Developer writes this -->
|
|
17
|
+
<template>
|
|
18
|
+
<div class="lsp7-transfer">
|
|
19
|
+
<div class="transfer-flow">
|
|
20
|
+
<AddressDisplay
|
|
21
|
+
:address="transaction.from"
|
|
22
|
+
:resolved="addressData[transaction.from]"
|
|
23
|
+
@click="$emit('address-click', transaction.from)"
|
|
24
|
+
/>
|
|
25
|
+
<div class="arrow">→</div>
|
|
26
|
+
<AddressDisplay
|
|
27
|
+
:address="transaction.to"
|
|
28
|
+
:resolved="addressData[transaction.to]"
|
|
29
|
+
/>
|
|
30
|
+
</div>
|
|
31
|
+
|
|
32
|
+
<div class="amount">
|
|
33
|
+
{{ formatAmount(transaction.amount) }} {{ transaction.symbol }}
|
|
34
|
+
</div>
|
|
35
|
+
|
|
36
|
+
<div v-if="showActions" class="actions">
|
|
37
|
+
<button @click="$emit('reject', transaction)">Reject</button>
|
|
38
|
+
<button @click="$emit('approve', transaction)">Approve</button>
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
</template>
|
|
42
|
+
|
|
43
|
+
<script setup>
|
|
44
|
+
import { useTransactionView } from '@lukso/transaction-view-headless'
|
|
45
|
+
|
|
46
|
+
const props = defineProps(['transaction', 'showActions'])
|
|
47
|
+
const emit = defineEmits(['approve', 'reject', 'address-click'])
|
|
48
|
+
|
|
49
|
+
const { addressData, formatAmount } = useTransactionView(props.transaction, {
|
|
50
|
+
framework: 'lit' // Still uses headless system
|
|
51
|
+
})
|
|
52
|
+
</script>
|
|
53
|
+
|
|
54
|
+
<style scoped>
|
|
55
|
+
.lsp7-transfer { padding: 16px; }
|
|
56
|
+
.transfer-flow { display: flex; align-items: center; gap: 12px; }
|
|
57
|
+
.amount { font-size: 18px; font-weight: bold; }
|
|
58
|
+
</style>`,
|
|
59
|
+
|
|
60
|
+
// Build tool compiles to Lit (universal)
|
|
61
|
+
compiled: `
|
|
62
|
+
// lsp7-transfer-view.ts - Build tool generates this
|
|
63
|
+
import { LitElement, html, css } from 'lit'
|
|
64
|
+
import { customElement, property } from 'lit/decorators.js'
|
|
65
|
+
import { useTransactionView } from '@lukso/transaction-view-headless'
|
|
66
|
+
|
|
67
|
+
@customElement('lsp7-transfer-view')
|
|
68
|
+
export class LSP7TransferView extends LitElement {
|
|
69
|
+
@property({ type: Object }) transaction = null
|
|
70
|
+
@property({ type: Boolean }) showActions = false
|
|
71
|
+
|
|
72
|
+
private addressData = {}
|
|
73
|
+
private formatAmount = (x) => x
|
|
74
|
+
|
|
75
|
+
override async connectedCallback() {
|
|
76
|
+
super.connectedCallback()
|
|
77
|
+
if (this.transaction) {
|
|
78
|
+
const viewData = await useTransactionView(this.transaction, {
|
|
79
|
+
framework: 'lit'
|
|
80
|
+
})
|
|
81
|
+
this.addressData = viewData.addressData
|
|
82
|
+
this.formatAmount = viewData.formatAmount
|
|
83
|
+
this.requestUpdate()
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
override render() {
|
|
88
|
+
return html\`
|
|
89
|
+
<div class="lsp7-transfer">
|
|
90
|
+
<div class="transfer-flow">
|
|
91
|
+
<address-display
|
|
92
|
+
.address=\${this.transaction.from}
|
|
93
|
+
.resolved=\${this.addressData[this.transaction.from]}
|
|
94
|
+
@click=\${() => this._emit('address-click', this.transaction.from)}
|
|
95
|
+
></address-display>
|
|
96
|
+
<div class="arrow">→</div>
|
|
97
|
+
<address-display
|
|
98
|
+
.address=\${this.transaction.to}
|
|
99
|
+
.resolved=\${this.addressData[this.transaction.to]}
|
|
100
|
+
></address-display>
|
|
101
|
+
</div>
|
|
102
|
+
|
|
103
|
+
<div class="amount">
|
|
104
|
+
\${this.formatAmount(this.transaction.amount)} \${this.transaction.symbol}
|
|
105
|
+
</div>
|
|
106
|
+
|
|
107
|
+
\${this.showActions ? html\`
|
|
108
|
+
<div class="actions">
|
|
109
|
+
<button @click=\${() => this._emit('reject', this.transaction)}>
|
|
110
|
+
Reject
|
|
111
|
+
</button>
|
|
112
|
+
<button @click=\${() => this._emit('approve', this.transaction)}>
|
|
113
|
+
Approve
|
|
114
|
+
</button>
|
|
115
|
+
</div>
|
|
116
|
+
\` : ''}
|
|
117
|
+
</div>
|
|
118
|
+
\`
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
static styles = css\`
|
|
122
|
+
.lsp7-transfer { padding: 16px; }
|
|
123
|
+
.transfer-flow { display: flex; align-items: center; gap: 12px; }
|
|
124
|
+
.amount { font-size: 18px; font-weight: bold; }
|
|
125
|
+
\`
|
|
126
|
+
|
|
127
|
+
private _emit(eventName, detail) {
|
|
128
|
+
this.dispatchEvent(new CustomEvent(eventName, { detail, bubbles: true }))
|
|
129
|
+
}
|
|
130
|
+
}`,
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* React to Lit compilation (using existing tools)
|
|
135
|
+
*/
|
|
136
|
+
export const ReactToLitCompilation = {
|
|
137
|
+
// Developer writes React
|
|
138
|
+
source: `
|
|
139
|
+
// LSP7Transfer.jsx - Developer writes this
|
|
140
|
+
import { useTransactionView } from '@lukso/transaction-view-headless'
|
|
141
|
+
|
|
142
|
+
export function LSP7Transfer({ transaction, showActions, onApprove, onReject, onAddressClick }) {
|
|
143
|
+
const { addressData, formatAmount } = useTransactionView(transaction, {
|
|
144
|
+
framework: 'lit'
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
return (
|
|
148
|
+
<div className="lsp7-transfer">
|
|
149
|
+
<div className="transfer-flow">
|
|
150
|
+
<AddressDisplay
|
|
151
|
+
address={transaction.from}
|
|
152
|
+
resolved={addressData[transaction.from]}
|
|
153
|
+
onClick={() => onAddressClick?.(transaction.from)}
|
|
154
|
+
/>
|
|
155
|
+
<div className="arrow">→</div>
|
|
156
|
+
<AddressDisplay
|
|
157
|
+
address={transaction.to}
|
|
158
|
+
resolved={addressData[transaction.to]}
|
|
159
|
+
/>
|
|
160
|
+
</div>
|
|
161
|
+
|
|
162
|
+
<div className="amount">
|
|
163
|
+
{formatAmount(transaction.amount)} {transaction.symbol}
|
|
164
|
+
</div>
|
|
165
|
+
|
|
166
|
+
{showActions && (
|
|
167
|
+
<div className="actions">
|
|
168
|
+
<button onClick={() => onReject?.(transaction)}>Reject</button>
|
|
169
|
+
<button onClick={() => onApprove?.(transaction)}>Approve</button>
|
|
170
|
+
</div>
|
|
171
|
+
)}
|
|
172
|
+
</div>
|
|
173
|
+
)
|
|
174
|
+
}`,
|
|
175
|
+
|
|
176
|
+
// Tools like @lit-labs/react-to-lit could handle compilation
|
|
177
|
+
compiled: `// Same Lit output as above, but compiled from React`,
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Existing tools for compilation approaches
|
|
182
|
+
*/
|
|
183
|
+
export const ExistingTools = {
|
|
184
|
+
vueToWebComponents: `
|
|
185
|
+
// Vue has built-in web component compilation!
|
|
186
|
+
// vue.config.js
|
|
187
|
+
module.exports = {
|
|
188
|
+
configureWebpack: {
|
|
189
|
+
output: {
|
|
190
|
+
libraryTarget: 'system'
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Build command
|
|
196
|
+
vue-cli-service build --target lib --name lsp7-transfer src/LSP7Transfer.vue
|
|
197
|
+
|
|
198
|
+
// Outputs: Custom element that works everywhere!`,
|
|
199
|
+
|
|
200
|
+
reactToWebComponents: `
|
|
201
|
+
// Multiple options for React -> Web Components:
|
|
202
|
+
|
|
203
|
+
// 1. Stencil.js (most mature)
|
|
204
|
+
import { Component, Prop, h } from '@stencil/core'
|
|
205
|
+
|
|
206
|
+
@Component({ tag: 'lsp7-transfer-view' })
|
|
207
|
+
export class LSP7Transfer {
|
|
208
|
+
@Prop() transaction: any
|
|
209
|
+
|
|
210
|
+
render() {
|
|
211
|
+
return <div>...</div> // JSX works in Stencil
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// 2. @lit-labs/react (experimental)
|
|
216
|
+
// 3. Preact with custom elements
|
|
217
|
+
// 4. React 18's upcoming web components support`,
|
|
218
|
+
|
|
219
|
+
buildToolIntegration: `
|
|
220
|
+
// Custom build tool integration
|
|
221
|
+
// packages/decoder-web-components/build.config.js
|
|
222
|
+
|
|
223
|
+
export default {
|
|
224
|
+
input: {
|
|
225
|
+
'vue-components': './src/vue/**/*.vue',
|
|
226
|
+
'react-components': './src/react/**/*.jsx'
|
|
227
|
+
},
|
|
228
|
+
|
|
229
|
+
plugins: [
|
|
230
|
+
vueToLit(), // Custom plugin
|
|
231
|
+
reactToLit(), // Custom plugin
|
|
232
|
+
],
|
|
233
|
+
|
|
234
|
+
output: {
|
|
235
|
+
dir: 'dist/web-components',
|
|
236
|
+
format: 'es'
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Result: Universal web components from familiar source code`,
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* The developer experience strategy
|
|
245
|
+
*/
|
|
246
|
+
export const DeveloperExperienceStrategy = {
|
|
247
|
+
// Phase 1: Start with Lit (for the brave)
|
|
248
|
+
phase1: `
|
|
249
|
+
Let experienced developers write Lit directly:
|
|
250
|
+
- Better performance (no compilation overhead)
|
|
251
|
+
- Full control over web component lifecycle
|
|
252
|
+
- Direct access to Shadow DOM features
|
|
253
|
+
- Learning opportunity for modern web standards`,
|
|
254
|
+
|
|
255
|
+
// Phase 2: Compilation escape hatch (for the complainers)
|
|
256
|
+
phase2: `
|
|
257
|
+
If developers really complain:
|
|
258
|
+
- Vue developers can write .vue files
|
|
259
|
+
- React developers can write JSX
|
|
260
|
+
- Build tool compiles to Lit web components
|
|
261
|
+
- Everyone gets the same universal output
|
|
262
|
+
- "You can write Vue, but you're shipping Lit" 😈`,
|
|
263
|
+
|
|
264
|
+
// Phase 3: Best of both worlds
|
|
265
|
+
phase3: `
|
|
266
|
+
Mixed approach:
|
|
267
|
+
- Complex components: Write in Lit (full control)
|
|
268
|
+
- Simple components: Write in Vue/React (faster development)
|
|
269
|
+
- Build system handles compilation
|
|
270
|
+
- All output universal web components
|
|
271
|
+
- Developers pick their poison per component`,
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Package structure with compilation support
|
|
276
|
+
*/
|
|
277
|
+
export const CompilationPackageStructure = `
|
|
278
|
+
packages/
|
|
279
|
+
├── decoder-headless/ # Business logic
|
|
280
|
+
│
|
|
281
|
+
├── decoder-web-components/ # The universal output
|
|
282
|
+
│ ├── dist/ # Compiled web components
|
|
283
|
+
│ │ ├── lsp7-transfer-view.js # Universal web component
|
|
284
|
+
│ │ ├── lsp8-transfer-view.js # Works in all frameworks
|
|
285
|
+
│ │ └── execute-batch-view.js # Ships to production
|
|
286
|
+
│ │
|
|
287
|
+
│ ├── src/ # Source can be mixed!
|
|
288
|
+
│ │ ├── lit/ # Hand-written Lit (performance-critical)
|
|
289
|
+
│ │ │ └── complex-transaction.ts # When you need full control
|
|
290
|
+
│ │ ├── vue/ # Vue source (developer-friendly)
|
|
291
|
+
│ │ │ ├── LSP7Transfer.vue # Compiled to web component
|
|
292
|
+
│ │ │ └── LSP8Transfer.vue # Vue DX, Lit output
|
|
293
|
+
│ │ └── react/ # React source (developer-friendly)
|
|
294
|
+
│ │ └── ExecuteBatch.jsx # JSX DX, Lit output
|
|
295
|
+
│ │
|
|
296
|
+
│ ├── build.config.js # Handles all compilation
|
|
297
|
+
│ └── package.json
|
|
298
|
+
│
|
|
299
|
+
└── decoder-react-native/ # Mobile native (no compilation)
|
|
300
|
+
└── src/ # Pure React Native
|
|
301
|
+
├── LSP7Transfer.jsx
|
|
302
|
+
└── ExecuteBatch.jsx
|
|
303
|
+
`
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* The ultimate developer suffering mitigation strategy 😈
|
|
307
|
+
*/
|
|
308
|
+
export const DeveloperSufferingMitigation = `
|
|
309
|
+
🎠THE STRATEGY: "Suffer Now, Benefit Later"
|
|
310
|
+
|
|
311
|
+
Level 1 - The Brave: Write Lit directly
|
|
312
|
+
- Get full control and best performance
|
|
313
|
+
- Learn modern web standards
|
|
314
|
+
- Become web component experts
|
|
315
|
+
- Suffer the learning curve BUT gain superpowers
|
|
316
|
+
|
|
317
|
+
Level 2 - The Practical: Use compilation
|
|
318
|
+
- Write Vue/React (comfortable)
|
|
319
|
+
- Build tool outputs Lit (universal)
|
|
320
|
+
- Get universality without the learning curve
|
|
321
|
+
- Slight build complexity but familiar DX
|
|
322
|
+
|
|
323
|
+
Level 3 - The Lazy: Use existing tools
|
|
324
|
+
- Vue's built-in web component build
|
|
325
|
+
- Stencil for React-like JSX
|
|
326
|
+
- Let tooling handle the suffering
|
|
327
|
+
|
|
328
|
+
RESULT:
|
|
329
|
+
- Developers get to choose their suffering level
|
|
330
|
+
- Users always get universal web components
|
|
331
|
+
- Maintainers only ship one implementation per platform
|
|
332
|
+
- Everyone wins (eventually) 🎉
|
|
333
|
+
|
|
334
|
+
The suffering is temporary, but the universality is forever! 😈✨
|
|
335
|
+
`
|
|
336
|
+
|
|
337
|
+
export const Conclusion = `
|
|
338
|
+
🤯 THIS IS ACTUALLY BRILLIANT:
|
|
339
|
+
|
|
340
|
+
1. Ship universal web components (Lit output)
|
|
341
|
+
2. Let developers write in their preferred framework (Vue/React source)
|
|
342
|
+
3. Build tools handle the compilation (tooling suffers so humans don't have to)
|
|
343
|
+
4. React Native stays native (mobile optimization)
|
|
344
|
+
5. Everyone gets what they want:
|
|
345
|
+
- Users: Universal components that work everywhere
|
|
346
|
+
- Vue devs: Can write .vue files
|
|
347
|
+
- React devs: Can write JSX
|
|
348
|
+
- Maintainers: Only ship 2 implementations
|
|
349
|
+
- Framework wars: Become irrelevant 😎
|
|
350
|
+
|
|
351
|
+
The compilation approach gives you the BEST of both worlds:
|
|
352
|
+
- Developer Experience: Write in familiar frameworks
|
|
353
|
+
- User Experience: Universal web components
|
|
354
|
+
- Maintenance Experience: Minimal implementations
|
|
355
|
+
|
|
356
|
+
Let them write Vue, ship Lit. Let them write React, ship Lit.
|
|
357
|
+
The frameworks become implementation details! ðŸŽ
|
|
358
|
+
`
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TanStack Query integration for address resolution
|
|
3
|
+
* Provides proper cache keys and query functions
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { ResolvedAddress } from './useAddressResolution'
|
|
7
|
+
import { resolveAddress, resolveAddresses } from './useAddressResolution'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Create TanStack Query key for address resolution
|
|
11
|
+
*/
|
|
12
|
+
export function getAddressQueryKey(
|
|
13
|
+
address: string,
|
|
14
|
+
chainId?: number
|
|
15
|
+
): (string | number)[] {
|
|
16
|
+
// Include chainId to ensure cache isolation per chain
|
|
17
|
+
return ['address', address.toLowerCase(), chainId || 'current']
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Create TanStack Query key for batch address resolution
|
|
22
|
+
*/
|
|
23
|
+
export function getAddressesQueryKey(
|
|
24
|
+
addresses: string[],
|
|
25
|
+
chainId?: number
|
|
26
|
+
): (string | number)[] {
|
|
27
|
+
// Sort addresses for consistent cache keys
|
|
28
|
+
const sortedAddresses = [...addresses]
|
|
29
|
+
.map((addr) => addr.toLowerCase())
|
|
30
|
+
.sort()
|
|
31
|
+
return ['addresses', sortedAddresses.join(','), chainId || 'current']
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Query function for single address resolution
|
|
36
|
+
*/
|
|
37
|
+
export async function queryAddress({
|
|
38
|
+
queryKey,
|
|
39
|
+
}: {
|
|
40
|
+
queryKey: (string | number)[]
|
|
41
|
+
}): Promise<ResolvedAddress> {
|
|
42
|
+
const [, address, chainIdOrCurrent] = queryKey
|
|
43
|
+
const chainId =
|
|
44
|
+
chainIdOrCurrent === 'current' ? undefined : (chainIdOrCurrent as number)
|
|
45
|
+
|
|
46
|
+
return resolveAddress(address as string, chainId)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Query function for batch address resolution
|
|
51
|
+
*/
|
|
52
|
+
export async function queryAddresses({
|
|
53
|
+
queryKey,
|
|
54
|
+
}: {
|
|
55
|
+
queryKey: (string | number)[]
|
|
56
|
+
}): Promise<Map<string, ResolvedAddress>> {
|
|
57
|
+
const [, addressesStr, chainIdOrCurrent] = queryKey
|
|
58
|
+
const chainId =
|
|
59
|
+
chainIdOrCurrent === 'current' ? undefined : (chainIdOrCurrent as number)
|
|
60
|
+
const addresses = (addressesStr as string).split(',')
|
|
61
|
+
|
|
62
|
+
return resolveAddresses(addresses, chainId)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Helper for React TanStack Query usage
|
|
67
|
+
*/
|
|
68
|
+
export const addressQueryOptions = {
|
|
69
|
+
/**
|
|
70
|
+
* Single address query options
|
|
71
|
+
*/
|
|
72
|
+
single: (address: string, chainId?: number) => ({
|
|
73
|
+
queryKey: getAddressQueryKey(address, chainId),
|
|
74
|
+
queryFn: queryAddress,
|
|
75
|
+
staleTime: 5 * 60 * 1000, // 5 minutes
|
|
76
|
+
gcTime: 10 * 60 * 1000, // 10 minutes (formerly cacheTime)
|
|
77
|
+
}),
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Batch addresses query options
|
|
81
|
+
*/
|
|
82
|
+
batch: (addresses: string[], chainId?: number) => ({
|
|
83
|
+
queryKey: getAddressesQueryKey(addresses, chainId),
|
|
84
|
+
queryFn: queryAddresses,
|
|
85
|
+
staleTime: 5 * 60 * 1000, // 5 minutes
|
|
86
|
+
gcTime: 10 * 60 * 1000, // 10 minutes
|
|
87
|
+
}),
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Helper for Vue TanStack Query usage
|
|
92
|
+
*/
|
|
93
|
+
export const addressQueryOptionsVue = {
|
|
94
|
+
/**
|
|
95
|
+
* Single address query options for Vue Query
|
|
96
|
+
*/
|
|
97
|
+
single: (address: string, chainId?: number) => ({
|
|
98
|
+
queryKey: getAddressQueryKey(address, chainId),
|
|
99
|
+
queryFn: queryAddress,
|
|
100
|
+
staleTime: 5 * 60 * 1000,
|
|
101
|
+
cacheTime: 10 * 60 * 1000, // Vue Query still uses cacheTime
|
|
102
|
+
}),
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Batch addresses query options for Vue Query
|
|
106
|
+
*/
|
|
107
|
+
batch: (addresses: string[], chainId?: number) => ({
|
|
108
|
+
queryKey: getAddressesQueryKey(addresses, chainId),
|
|
109
|
+
queryFn: queryAddresses,
|
|
110
|
+
staleTime: 5 * 60 * 1000,
|
|
111
|
+
cacheTime: 10 * 60 * 1000,
|
|
112
|
+
}),
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Invalidate address cache for a specific chain
|
|
117
|
+
* Useful when switching chains
|
|
118
|
+
*/
|
|
119
|
+
export function getInvalidateAddressesPattern(
|
|
120
|
+
chainId?: number
|
|
121
|
+
): (string | number)[] {
|
|
122
|
+
return ['address', chainId || 'current']
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Get all possible query keys for an address across all chains
|
|
127
|
+
* Useful for invalidating cache when address profile changes
|
|
128
|
+
*/
|
|
129
|
+
export function getAllAddressQueryKeys(address: string): (string | number)[][] {
|
|
130
|
+
return [
|
|
131
|
+
['address', address.toLowerCase(), 'current'],
|
|
132
|
+
['address', address.toLowerCase(), 42], // mainnet
|
|
133
|
+
['address', address.toLowerCase(), 4201], // testnet
|
|
134
|
+
]
|
|
135
|
+
}
|