@1001-digital/components 0.0.2 → 0.0.3
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/package.json +3 -7
- package/src/base/components/Dialog.vue +2 -1
- package/src/base/components/Toasts.vue +23 -1
- package/src/base/composables/toast.ts +1 -0
- package/src/evm/components/EvmTransactionFlow.vue +5 -10
- package/src/evm/composables/ens.ts +31 -14
- package/src/evm/composables/gasPrice.ts +4 -3
- package/src/evm/composables/priceFeed.ts +17 -8
- package/src/evm/utils/ens.ts +19 -4
- package/src/evm/utils/price.ts +4 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@1001-digital/components",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": [
|
|
6
6
|
"*.css"
|
|
@@ -13,16 +13,12 @@
|
|
|
13
13
|
"src"
|
|
14
14
|
],
|
|
15
15
|
"peerDependencies": {
|
|
16
|
-
"@wagmi/
|
|
17
|
-
"@wagmi/vue": ">=0.4.0",
|
|
16
|
+
"@wagmi/vue": ">=0.5.0",
|
|
18
17
|
"viem": ">=2.0.0",
|
|
19
18
|
"vue": "^3.5.0",
|
|
20
|
-
"@1001-digital/styles": "^0.0.
|
|
19
|
+
"@1001-digital/styles": "^0.0.2"
|
|
21
20
|
},
|
|
22
21
|
"peerDependenciesMeta": {
|
|
23
|
-
"@wagmi/core": {
|
|
24
|
-
"optional": true
|
|
25
|
-
},
|
|
26
22
|
"@wagmi/vue": {
|
|
27
23
|
"optional": true
|
|
28
24
|
},
|
|
@@ -250,9 +250,10 @@ const onClickOutside = () => {
|
|
|
250
250
|
> footer {
|
|
251
251
|
display: flex;
|
|
252
252
|
gap: var(--spacer);
|
|
253
|
-
justify-content: flex-end;
|
|
253
|
+
justify-content: safe flex-end;
|
|
254
254
|
padding: var(--spacer);
|
|
255
255
|
border-block-start: var(--border);
|
|
256
|
+
overflow-x: auto;
|
|
256
257
|
|
|
257
258
|
&:empty {
|
|
258
259
|
display: none;
|
|
@@ -13,6 +13,11 @@
|
|
|
13
13
|
@update:open="(open) => !open && onClose(toast.id)"
|
|
14
14
|
>
|
|
15
15
|
<ToastTitle class="toast-title">
|
|
16
|
+
<span
|
|
17
|
+
v-if="toast.loading"
|
|
18
|
+
class="toast-spinner"
|
|
19
|
+
aria-hidden="true"
|
|
20
|
+
/>
|
|
16
21
|
{{ toast.title }}
|
|
17
22
|
</ToastTitle>
|
|
18
23
|
<ToastClose
|
|
@@ -37,7 +42,7 @@
|
|
|
37
42
|
class="left"
|
|
38
43
|
>
|
|
39
44
|
<Button
|
|
40
|
-
class="small"
|
|
45
|
+
class="small tertiary"
|
|
41
46
|
@click="toast.action!.onClick()"
|
|
42
47
|
>
|
|
43
48
|
{{ toast.action.label }}
|
|
@@ -211,6 +216,7 @@ const onClose = (id: string) => {
|
|
|
211
216
|
.toast-title {
|
|
212
217
|
display: flex;
|
|
213
218
|
align-items: center;
|
|
219
|
+
gap: var(--spacer-sm);
|
|
214
220
|
block-size: calc(var(--spacer) * 2);
|
|
215
221
|
box-shadow: var(--border-shadow);
|
|
216
222
|
padding-inline-start: var(--ui-padding-inline);
|
|
@@ -222,6 +228,16 @@ const onClose = (id: string) => {
|
|
|
222
228
|
margin: 0;
|
|
223
229
|
}
|
|
224
230
|
|
|
231
|
+
.toast-spinner {
|
|
232
|
+
width: var(--ui-font-size);
|
|
233
|
+
height: var(--ui-font-size);
|
|
234
|
+
border: 2px solid currentColor;
|
|
235
|
+
border-top-color: transparent;
|
|
236
|
+
border-radius: 50%;
|
|
237
|
+
animation: spin var(--speed-slow, 1s) linear infinite;
|
|
238
|
+
flex-shrink: 0;
|
|
239
|
+
}
|
|
240
|
+
|
|
225
241
|
> section {
|
|
226
242
|
padding: var(--ui-padding-inline);
|
|
227
243
|
display: grid;
|
|
@@ -250,5 +266,11 @@ const onClose = (id: string) => {
|
|
|
250
266
|
}
|
|
251
267
|
}
|
|
252
268
|
}
|
|
269
|
+
|
|
270
|
+
@keyframes spin {
|
|
271
|
+
to {
|
|
272
|
+
transform: rotate(360deg);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
253
275
|
}
|
|
254
276
|
</style>
|
|
@@ -22,13 +22,7 @@
|
|
|
22
22
|
:txt="text.lead[step] || ''"
|
|
23
23
|
/>
|
|
24
24
|
|
|
25
|
-
<p
|
|
26
|
-
v-if="
|
|
27
|
-
step !== 'requesting' &&
|
|
28
|
-
step !== 'error' &&
|
|
29
|
-
text.lead[step]
|
|
30
|
-
"
|
|
31
|
-
>
|
|
25
|
+
<p v-if="step !== 'requesting' && step !== 'error' && text.lead[step]">
|
|
32
26
|
{{ text.lead[step] }}
|
|
33
27
|
</p>
|
|
34
28
|
|
|
@@ -203,9 +197,7 @@ onBeforeUnmount(() => {
|
|
|
203
197
|
})
|
|
204
198
|
|
|
205
199
|
const canDismiss = computed(
|
|
206
|
-
() =>
|
|
207
|
-
props.dismissable &&
|
|
208
|
-
step.value !== 'requesting',
|
|
200
|
+
() => props.dismissable && step.value !== 'requesting',
|
|
209
201
|
)
|
|
210
202
|
|
|
211
203
|
const initializeRequest = async (request = cachedRequest.value) => {
|
|
@@ -245,6 +237,7 @@ const initializeRequest = async (request = cachedRequest.value) => {
|
|
|
245
237
|
title: text.value.title.waiting,
|
|
246
238
|
description: text.value.lead.waiting,
|
|
247
239
|
duration: Infinity,
|
|
240
|
+
loading: true,
|
|
248
241
|
action: {
|
|
249
242
|
label: 'View on Block Explorer',
|
|
250
243
|
onClick: () => window.open(link, '_blank'),
|
|
@@ -264,6 +257,7 @@ const initializeRequest = async (request = cachedRequest.value) => {
|
|
|
264
257
|
variant: 'success',
|
|
265
258
|
title: text.value.title.complete,
|
|
266
259
|
description: text.value.lead.complete,
|
|
260
|
+
loading: false,
|
|
267
261
|
...(props.autoCloseSuccess && { duration: props.delayAutoclose }),
|
|
268
262
|
})
|
|
269
263
|
} catch (e: unknown) {
|
|
@@ -277,6 +271,7 @@ const initializeRequest = async (request = cachedRequest.value) => {
|
|
|
277
271
|
variant: 'error',
|
|
278
272
|
title: text.value.title.error,
|
|
279
273
|
description: err.shortMessage || 'Transaction failed.',
|
|
274
|
+
loading: false,
|
|
280
275
|
})
|
|
281
276
|
}
|
|
282
277
|
console.log(e)
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { getPublicClient } from '@wagmi/core'
|
|
2
2
|
import type { Config } from '@wagmi/vue'
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
ensCache,
|
|
5
|
+
fetchEnsFromIndexer,
|
|
6
|
+
fetchEnsFromChain,
|
|
7
|
+
ENS_KEYS_AVATAR,
|
|
8
|
+
ENS_KEYS_PROFILE,
|
|
9
|
+
} from '../utils/ens'
|
|
4
10
|
import type { EnsProfile } from '../utils/ens'
|
|
5
11
|
|
|
6
12
|
type EnsMode = 'indexer' | 'chain'
|
|
@@ -10,12 +16,14 @@ interface UseEnsOptions {
|
|
|
10
16
|
}
|
|
11
17
|
|
|
12
18
|
interface EnsRuntimeConfig {
|
|
13
|
-
ens?: { indexer1?: string
|
|
19
|
+
ens?: { indexer1?: string; indexer2?: string; indexer3?: string }
|
|
14
20
|
}
|
|
15
21
|
|
|
16
22
|
function getIndexerUrls(config: EnsRuntimeConfig): string[] {
|
|
17
23
|
if (!config.ens) return []
|
|
18
|
-
return [config.ens.indexer1, config.ens.indexer2, config.ens.indexer3].filter(
|
|
24
|
+
return [config.ens.indexer1, config.ens.indexer2, config.ens.indexer3].filter(
|
|
25
|
+
Boolean,
|
|
26
|
+
) as string[]
|
|
19
27
|
}
|
|
20
28
|
|
|
21
29
|
async function resolve(
|
|
@@ -55,8 +63,12 @@ function useEnsBase(
|
|
|
55
63
|
const appConfig = useAppConfig()
|
|
56
64
|
const runtimeConfig = useRuntimeConfig()
|
|
57
65
|
|
|
58
|
-
const mode = computed<EnsMode>(
|
|
59
|
-
|
|
66
|
+
const mode = computed<EnsMode>(
|
|
67
|
+
() => toValue(options.mode) || appConfig.evm?.ens?.mode || 'indexer',
|
|
68
|
+
)
|
|
69
|
+
const indexerUrls = computed(() =>
|
|
70
|
+
getIndexerUrls(runtimeConfig.public.evm as EnsRuntimeConfig),
|
|
71
|
+
)
|
|
60
72
|
const cacheKey = computed(() => `ens-${tier}-${toValue(identifier)}`)
|
|
61
73
|
|
|
62
74
|
return useAsyncData(
|
|
@@ -65,9 +77,8 @@ function useEnsBase(
|
|
|
65
77
|
const id = toValue(identifier)
|
|
66
78
|
if (!id) return null
|
|
67
79
|
|
|
68
|
-
const strategies: EnsMode[] =
|
|
69
|
-
? ['indexer', 'chain']
|
|
70
|
-
: ['chain', 'indexer']
|
|
80
|
+
const strategies: EnsMode[] =
|
|
81
|
+
mode.value === 'indexer' ? ['indexer', 'chain'] : ['chain', 'indexer']
|
|
71
82
|
|
|
72
83
|
return ensCache.fetch(cacheKey.value, () =>
|
|
73
84
|
resolve(id, strategies, indexerUrls.value, $wagmi as Config, chainKeys),
|
|
@@ -80,11 +91,17 @@ function useEnsBase(
|
|
|
80
91
|
)
|
|
81
92
|
}
|
|
82
93
|
|
|
83
|
-
export const useEns = (
|
|
84
|
-
|
|
94
|
+
export const useEns = (
|
|
95
|
+
identifier: MaybeRefOrGetter<string | undefined>,
|
|
96
|
+
options?: UseEnsOptions,
|
|
97
|
+
) => useEnsBase('resolve', identifier, [], options)
|
|
85
98
|
|
|
86
|
-
export const useEnsWithAvatar = (
|
|
87
|
-
|
|
99
|
+
export const useEnsWithAvatar = (
|
|
100
|
+
identifier: MaybeRefOrGetter<string | undefined>,
|
|
101
|
+
options?: UseEnsOptions,
|
|
102
|
+
) => useEnsBase('avatar', identifier, [...ENS_KEYS_AVATAR], options)
|
|
88
103
|
|
|
89
|
-
export const useEnsProfile = (
|
|
90
|
-
|
|
104
|
+
export const useEnsProfile = (
|
|
105
|
+
identifier: MaybeRefOrGetter<string | undefined>,
|
|
106
|
+
options?: UseEnsOptions,
|
|
107
|
+
) => useEnsBase('profile', identifier, [...ENS_KEYS_PROFILE], options)
|
|
@@ -25,9 +25,10 @@ export const useGasPrice = () => {
|
|
|
25
25
|
eth: formatEther(price.value),
|
|
26
26
|
|
|
27
27
|
formatted: {
|
|
28
|
-
gwei:
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
gwei:
|
|
29
|
+
price.value > 2_000_000_000_000n
|
|
30
|
+
? Math.round(parseFloat(formatGwei(price.value)))
|
|
31
|
+
: parseFloat(formatGwei(price.value)).toFixed(1),
|
|
31
32
|
eth: formatEther(price.value),
|
|
32
33
|
},
|
|
33
34
|
}))
|
|
@@ -53,10 +53,13 @@ function saveToStorage() {
|
|
|
53
53
|
if (typeof window === 'undefined') return
|
|
54
54
|
|
|
55
55
|
try {
|
|
56
|
-
localStorage.setItem(
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
56
|
+
localStorage.setItem(
|
|
57
|
+
STORAGE_KEY,
|
|
58
|
+
stringifyJSON({
|
|
59
|
+
ethUSDRaw: state.ethUSDRaw,
|
|
60
|
+
lastUpdated: state.lastUpdated,
|
|
61
|
+
}),
|
|
62
|
+
)
|
|
60
63
|
} catch {
|
|
61
64
|
// Ignore storage errors
|
|
62
65
|
}
|
|
@@ -68,12 +71,18 @@ export const usePriceFeed = () => {
|
|
|
68
71
|
// Load cached data on first use
|
|
69
72
|
if (!state.lastUpdated) loadFromStorage()
|
|
70
73
|
|
|
71
|
-
const ethUSD = computed(() =>
|
|
72
|
-
|
|
73
|
-
|
|
74
|
+
const ethUSD = computed(() =>
|
|
75
|
+
state.ethUSDRaw ? state.ethUSDRaw / BigInt(1e8) : 0n,
|
|
76
|
+
)
|
|
77
|
+
const ethUSC = computed(() =>
|
|
78
|
+
state.ethUSDRaw ? state.ethUSDRaw / BigInt(1e6) : 0n,
|
|
79
|
+
)
|
|
80
|
+
const ethUSDFormatted = computed(() =>
|
|
81
|
+
formatPrice(Number(ethUSC.value) / 100, 2),
|
|
82
|
+
)
|
|
74
83
|
|
|
75
84
|
const weiToUSD = (wei: bigint) => {
|
|
76
|
-
const cents = (wei * (state.ethUSDRaw || 0n)) /
|
|
85
|
+
const cents = (wei * (state.ethUSDRaw || 0n)) / 10n ** 18n / 10n ** 6n
|
|
77
86
|
return formatPrice(Number(cents) / 100, 2)
|
|
78
87
|
}
|
|
79
88
|
|
package/src/evm/utils/ens.ts
CHANGED
|
@@ -22,7 +22,15 @@ export interface EnsProfile {
|
|
|
22
22
|
|
|
23
23
|
// --- Text record keys ---
|
|
24
24
|
|
|
25
|
-
const ALL_KEYS = [
|
|
25
|
+
const ALL_KEYS = [
|
|
26
|
+
'avatar',
|
|
27
|
+
'header',
|
|
28
|
+
'description',
|
|
29
|
+
'url',
|
|
30
|
+
'email',
|
|
31
|
+
'com.twitter',
|
|
32
|
+
'com.github',
|
|
33
|
+
] as const
|
|
26
34
|
|
|
27
35
|
export const ENS_KEYS_AVATAR = ['avatar'] as const
|
|
28
36
|
export const ENS_KEYS_PROFILE = [...ALL_KEYS]
|
|
@@ -62,7 +70,7 @@ export async function fetchEnsFromChain(
|
|
|
62
70
|
|
|
63
71
|
if (isAddr) {
|
|
64
72
|
address = identifier
|
|
65
|
-
ens = await client.getEnsName({ address: identifier as Address }) ?? null
|
|
73
|
+
ens = (await client.getEnsName({ address: identifier as Address })) ?? null
|
|
66
74
|
} else {
|
|
67
75
|
ens = identifier
|
|
68
76
|
const resolved = await client.getEnsAddress({ name: normalize(identifier) })
|
|
@@ -74,10 +82,17 @@ export async function fetchEnsFromChain(
|
|
|
74
82
|
|
|
75
83
|
const name = normalize(ens)
|
|
76
84
|
const results = await Promise.all(
|
|
77
|
-
keys.map(key => client.getEnsText({ name, key }).catch(() => null)),
|
|
85
|
+
keys.map((key) => client.getEnsText({ name, key }).catch(() => null)),
|
|
78
86
|
)
|
|
79
87
|
|
|
80
|
-
return {
|
|
88
|
+
return {
|
|
89
|
+
address,
|
|
90
|
+
ens,
|
|
91
|
+
data: toProfileData(
|
|
92
|
+
keys,
|
|
93
|
+
results.map((r) => r || ''),
|
|
94
|
+
),
|
|
95
|
+
}
|
|
81
96
|
}
|
|
82
97
|
|
|
83
98
|
// --- Helpers ---
|
package/src/evm/utils/price.ts
CHANGED
|
@@ -4,11 +4,13 @@ const replacer = (_: string, value: unknown) => {
|
|
|
4
4
|
}
|
|
5
5
|
|
|
6
6
|
const reviver = (_: string, value: unknown) => {
|
|
7
|
-
if (typeof value === 'string' && /^\d+n$/.test(value))
|
|
7
|
+
if (typeof value === 'string' && /^\d+n$/.test(value))
|
|
8
|
+
return BigInt(value.slice(0, -1))
|
|
8
9
|
return value
|
|
9
10
|
}
|
|
10
11
|
|
|
11
|
-
export const stringifyJSON = (obj: unknown): string =>
|
|
12
|
+
export const stringifyJSON = (obj: unknown): string =>
|
|
13
|
+
JSON.stringify(obj, replacer)
|
|
12
14
|
export const parseJSON = (json: string): unknown => JSON.parse(json, reviver)
|
|
13
15
|
|
|
14
16
|
export const formatPrice = (num: number, digits: number = 2) =>
|