Skip to content

Commit 82ac3c1

Browse files
trevormilclaude
andcommitted
Add EVM explorer redirect button for MsgEthereumTx transactions
Detects MsgEthereumTx messages and shows a button to view on the EVM explorer. Attempts to parse the EVM tx hash from events, falls back to block page if unavailable. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 8a972ed commit 82ac3c1

22 files changed

+2217
-1400
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
"build-only": "vite build",
1313
"type-check": "vue-tsc --noEmit",
1414
"generate-registry": "tsx scripts/generate-registry.ts",
15-
"push-k8s": "sleep 90 && kubectl delete -f ./k8s && kubectl apply -f ./k8s"
15+
"push-k8s": "sleep 150 && kubectl delete -f ./k8s && kubectl apply -f ./k8s",
16+
"push-k8s:no-sleep": "kubectl delete -f ./k8s && kubectl apply -f ./k8s"
1617
},
1718
"dependencies": {
1819
"@chain-registry/client": "^1.53.184",

src/components/CardStatisticsVertical.vue

Lines changed: 63 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,37 +19,83 @@ const isPositive = controlledComputed(
1919
() => props.change,
2020
() => Math.sign(props.change || 0) === 1
2121
);
22+
23+
const colorClasses = {
24+
primary: {
25+
bg: 'bg-indigo-100 dark:bg-indigo-500/10',
26+
text: 'text-indigo-500',
27+
glow: 'shadow-indigo-500/20',
28+
},
29+
success: {
30+
bg: 'bg-emerald-100 dark:bg-emerald-500/10',
31+
text: 'text-emerald-500',
32+
glow: 'shadow-emerald-500/20',
33+
},
34+
warning: {
35+
bg: 'bg-amber-100 dark:bg-amber-500/10',
36+
text: 'text-amber-500',
37+
glow: 'shadow-amber-500/20',
38+
},
39+
error: {
40+
bg: 'bg-red-100 dark:bg-red-500/10',
41+
text: 'text-red-500',
42+
glow: 'shadow-red-500/20',
43+
},
44+
info: {
45+
bg: 'bg-sky-100 dark:bg-sky-500/10',
46+
text: 'text-sky-500',
47+
glow: 'shadow-sky-500/20',
48+
},
49+
};
50+
51+
const getColorClass = (type: 'bg' | 'text' | 'glow') => {
52+
const colors = colorClasses[props.color as keyof typeof colorClasses] || colorClasses.primary;
53+
return colors[type];
54+
};
2255
</script>
2356

2457
<template>
25-
<div class="bg-base-100 shadow rounded p-4">
26-
<div class="flex items-center justify-center">
27-
<div v-if="props.icon" class="relative w-9 h-9 rounded overflow-hidden flex items-center justify-center">
28-
<Icon :class="[`text-${props?.color}`]" :icon="props.icon" size="32" />
29-
<div class="absolute top-0 left-0 bottom-0 right-0 opacity-20" :class="[`bg-${props?.color}`]"></div>
58+
<div class="card-modern p-5 group">
59+
<div class="flex items-start justify-between mb-4">
60+
<!-- Icon -->
61+
<div
62+
v-if="props.icon"
63+
class="w-12 h-12 rounded-xl flex items-center justify-center transition-transform duration-300 group-hover:scale-110"
64+
:class="[getColorClass('bg'), 'shadow-lg', getColorClass('glow')]"
65+
>
66+
<Icon :class="[getColorClass('text')]" :icon="props.icon" class="text-2xl" />
3067
</div>
3168

69+
<!-- Change indicator -->
3270
<div
33-
v-if="props.change"
34-
:class="isPositive ? 'text-success' : 'text-error'"
35-
class="flex items-center text-sm font-semibold"
71+
v-if="props.change !== undefined && props.change !== 0"
72+
class="flex items-center gap-0.5 text-sm font-semibold px-2 py-1 rounded-lg"
73+
:class="isPositive
74+
? 'bg-emerald-100 dark:bg-emerald-500/10 text-emerald-600 dark:text-emerald-400'
75+
: 'bg-red-100 dark:bg-red-500/10 text-red-600 dark:text-red-400'"
3676
>
77+
<Icon
78+
:icon="isPositive ? 'mdi:trending-up' : 'mdi:trending-down'"
79+
class="text-base"
80+
/>
3781
<span>{{ isPositive ? `+${props.change}` : props.change }}%</span>
38-
<Icon :icon="isPositive ? 'mdi-chevron-up' : 'mdi-chevron-down'" />
3982
</div>
4083
</div>
4184

42-
<div class="">
43-
<h6 class="text-lg text-center font-semibold mt-2 mb-1">
85+
<!-- Stats Value -->
86+
<div class="space-y-1">
87+
<h3 class="text-2xl font-bold text-slate-900 dark:text-white">
4488
{{ props.stats || '-' }}
45-
</h6>
46-
<p class="text-sm text-center">
89+
</h3>
90+
<p class="text-sm font-medium text-slate-500 dark:text-slate-400">
4791
{{ props.title }}
4892
</p>
49-
50-
<div v-if="props.subtitle" size="x-small" class="font-semibold">
51-
<span class="truncate">{{ props.subtitle }}</span>
52-
</div>
93+
<p
94+
v-if="props.subtitle"
95+
class="text-xs text-slate-400 dark:text-slate-500 truncate"
96+
>
97+
{{ props.subtitle }}
98+
</p>
5399
</div>
54100
</div>
55101
</template>

src/components/ChainSummary.vue

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,27 +19,50 @@ const addFavor = (e: Event) => {
1919
dashboardStore.favoriteMap[props.name] = !dashboardStore?.favoriteMap?.[props.name];
2020
window.localStorage.setItem('favoriteMap', JSON.stringify(dashboardStore.favoriteMap));
2121
};
22+
23+
const isFavorite = computed(() => dashboardStore?.favoriteMap?.[props.name]);
2224
</script>
25+
2326
<template>
2427
<RouterLink
2528
:to="`/${name}`"
26-
class="bg-base-100 hover:bg-gray-100 dark:hover:bg-[#373f59] rounded shadow flex items-center px-3 py-3 cursor-pointer"
29+
class="group card-modern p-4 flex items-center gap-4 cursor-pointer"
2730
>
28-
<div class="w-8 h-8 rounded-full overflow-hidden">
29-
<img :src="conf.logo" />
31+
<!-- Chain Logo -->
32+
<div class="relative">
33+
<div class="w-12 h-12 rounded-xl overflow-hidden bg-slate-100 dark:bg-slate-700 ring-2 ring-slate-200/50 dark:ring-slate-600/50 group-hover:ring-indigo-500/50 transition-all duration-300">
34+
<img
35+
:src="conf.logo"
36+
class="w-full h-full object-cover"
37+
:alt="conf?.prettyName || props.name"
38+
/>
39+
</div>
40+
<!-- Online indicator -->
41+
<div class="absolute -bottom-0.5 -right-0.5 w-3.5 h-3.5 rounded-full bg-emerald-500 border-2 border-white dark:border-slate-800"></div>
3042
</div>
31-
<div class="font-semibold ml-4 text-base flex-1 truncate capitalize">
32-
{{ conf?.prettyName || props.name }}
43+
44+
<!-- Chain Info -->
45+
<div class="flex-1 min-w-0">
46+
<h3 class="font-semibold text-slate-900 dark:text-white truncate group-hover:text-indigo-500 dark:group-hover:text-indigo-400 transition-colors">
47+
{{ conf?.prettyName || props.name }}
48+
</h3>
49+
<p class="text-xs text-slate-500 dark:text-slate-400 truncate capitalize">
50+
{{ props.name }}
51+
</p>
3352
</div>
34-
<div
53+
54+
<!-- Favorite Button -->
55+
<button
3556
@click="addFavor"
36-
class="pl-4 text-xl"
37-
:class="{
38-
'text-warning': dashboardStore?.favoriteMap?.[props.name],
39-
'text-gray-300 dark:text-gray-500': !dashboardStore?.favoriteMap?.[props.name],
40-
}"
57+
class="p-2 rounded-lg transition-all duration-200"
58+
:class="isFavorite
59+
? 'text-amber-500 bg-amber-100 dark:bg-amber-500/10'
60+
: 'text-slate-300 dark:text-slate-600 hover:text-amber-500 hover:bg-slate-100 dark:hover:bg-slate-700'"
4161
>
42-
<Icon icon="mdi-star" />
43-
</div>
62+
<Icon
63+
:icon="isFavorite ? 'mdi:star' : 'mdi:star-outline'"
64+
class="text-xl"
65+
/>
66+
</button>
4467
</RouterLink>
4568
</template>

0 commit comments

Comments
 (0)