Skip to content

Commit

Permalink
feat: add DisplayVariable
Browse files Browse the repository at this point in the history
  • Loading branch information
TomatoDroid committed Oct 8, 2024
1 parent d0e0c35 commit 37ed21a
Show file tree
Hide file tree
Showing 27 changed files with 928 additions and 344 deletions.
6 changes: 0 additions & 6 deletions nuxt/app.config.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,2 @@
export default defineAppConfig({
// ui: {
// notifications: {
// // Show toasts at the top right of the screen
// position: 'top-0 end-0',
// }
// }
})
2 changes: 2 additions & 0 deletions nuxt/app.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<script setup lang="ts">
import 'vue-toastification/dist/index.css'
useSeoMeta({
title: 'Scaffold-ETH-VUE App',
description: 'Built with 🏗 Scaffold-ETH-VUE',
Expand Down
Empty file added nuxt/assets/css/toast.css
Empty file.
9 changes: 8 additions & 1 deletion nuxt/components/HeaderMenuLinks.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
<script setup lang="ts">
export interface MenuProps {
label: string
link: string
icon?: string
}
defineProps<{
menu: ({ label: string, link: string, icon?: undefined })[]
menu: MenuProps[]
}>()
const route = useRoute()
Expand Down
2 changes: 1 addition & 1 deletion nuxt/components/TheNav.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ onClickOutside(drawOpenRef, () => {
</script>

<template>
<header class="sticky lg:static top-0 navbar bg-base-100 min-h-10 flex-shrink-0 justify-between z-20 shadow-md shadow-secondary px-0 sm:px-2">
<header class="sticky lg:static top-0 navbar bg-<Suspense> is an experimental feature and its API will likely change. min-h-10 flex-shrink-0 justify-between z-20 shadow-md shadow-secondary px-0 sm:px-2">
<div class="navbar-start">
<div class="dropdown lg:hidden">
<label
Expand Down
12 changes: 6 additions & 6 deletions nuxt/components/scaffold-eth/Balance.vue
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const formatterBalance = computed(() => {
</div>
<div
v-else-if="!address || isLoading || balance === null || (nativeCurrency.isFetching && nativeCurrency.price === 0)"
class="animate-pulse flex space-x-4"
class="animate-pulse flex space-x-4 items-center"
>
<div class="rounded-md bg-slate-300 h-6 w-6" />
<div class="flex items-center space-y-6">
Expand All @@ -48,15 +48,15 @@ const formatterBalance = computed(() => {
class="btn btn-sm btn-ghost flex items-center hover:bg-transparent"
@click="toggleDisplayUsdMode"
>
<div class="w-full">
<div v-if="displayUsdMode" class="flex items-center justify-center">
<div class="w-full flex items-center justify-center">
<template v-if="displayUsdMode">
<span class="text-[0.8em] font-bold mr-1">$</span>
<span>{{ formatterBalance * nativeCurrency.price }}</span>
</div>
<div v-else class="flex items-center justify-center">
</template>
<template v-else>
<span>{{ formatterBalance.toFixed(4) }}</span>
<span class="text-[0.8em] font-bold ml-1">{{ targetNetwork.nativeCurrency.symbol }}</span>
</div>
</template>
</div>
</button>
</template>
18 changes: 18 additions & 0 deletions nuxt/components/scaffold-eth/debug/ArrayDisplay.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<script setup lang="ts">
import type { DisplayContent, ResultFontSize } from './DisplayTxResult.vue'
defineProps<{
values: DisplayContent[]
size: ResultFontSize
}>()
</script>

<template>
<div class="flex flex-col gap-y-1">
{{ values.length ? 'array' : '[]' }}
<ObjectFieldDisplay
v-for="(value, key) in values"
:key="key" :name="`[${key}]`" :value="value" :size="size"
/>
</div>
</template>
51 changes: 51 additions & 0 deletions nuxt/components/scaffold-eth/debug/ContractUI.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<script setup lang="ts">
import type { ContractName } from '~/utils/scaffold-eth/contract'
const props = defineProps<{
contractName: ContractName
}>()
const { targetNetwork } = useTargetNetwork()
const networkColor = useNetworkColor()
const { data: deployedContractData, isLoading: deployedContractDataLoading } = useDeployedContractInfo(props.contractName)
</script>

<template>
<div v-if="deployedContractDataLoading" class="mt-14">
<span class="loading loading-spinner loading-lg" />
</div>
<p v-else-if="!deployedContractData" class="text-3xl mt-14">
{{ `No contract found by the name of "${contractName}" on chain "${targetNetwork.name}"!` }}
</p>
<div v-else class="grid grid-cols-1 lg:grid-cols-6 px-6 lg:px-10 lg:gap-12 w-full max-w-7xl my-0">
<div class="col-span-5 grid grid-cols-1 lg:grid-cols-3 gap-8 lg:gap-10">
<div class="col-span-1 flex flex-col">
<div class="bg-base-100 border-base-300 border shadow-md shadow-secondary rounded-3xl px-6 lg:px-8 mb-6 space-y-1 py-4">
<div class="flex">
<div class="flex flex-col gap-1">
<span class="font-bold">{{ contractName }}</span>
<Address :address="deployedContractData.address" />
<div class="flex gap-1 items-center">
<span class="font-bold text-sm">Balance:</span>
<Balance
:address="deployedContractData.address"
class="px-0 h-1.5 max-height-[0.375rem]"
/>
</div>
</div>
</div>
<p v-if="targetNetwork" class="my-0 text-sm gap-1 flex">
<span class="font-bold">network:</span>
<span :style="{ color: networkColor }">{{ targetNetwork.name }}</span>
</p>
</div>
<div class="bg-base-300 rounded-3xl px-6 lg:px-8 py-4 shadow-lg shadow-base-300">
<ContractVariables
:refresh-display-variables="true"
:deployed-contract-data="deployedContractData"
/>
</div>
</div>
</div>
</div>
</template>
35 changes: 35 additions & 0 deletions nuxt/components/scaffold-eth/debug/ContractVariables.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<script setup lang="ts">
import type { Abi, AbiFunction } from 'viem'
import type { Contract, ContractName, GenericContract, InheritedFunctions } from '~/utils/scaffold-eth/contract'
const props = defineProps<{
refreshDisplayVariables: boolean
deployedContractData: Contract<ContractName>
}>()
const functionsToData = computed(() => {
return ((props.deployedContractData.abi as Abi).filter(part => part.type === 'function') as AbiFunction[])
.filter(fn => (fn.stateMutability === 'view' || fn.stateMutability === 'pure') && fn.inputs.length === 0)
.map(fn => ({
fn,
inheritedFrom: ((props.deployedContractData as GenericContract)?.inheritedFunctions as InheritedFunctions)?.[fn.name],
}))
.sort((a, b) => b.inheritedFrom ? b.inheritedFrom.localeCompare(a.inheritedFrom) : 1)
})
</script>

<template>
<div v-if="!functionsToData.length">
No contract variables
</div>
<DisplayVariable
v-for="{ fn, inheritedFrom } in functionsToData"
v-else
:key="fn.name"
:abi-function="fn"
:abi="deployedContractData.abi"
:contract-address="deployedContractData.address"
:refresh-display-variables="refreshDisplayVariables"
:inherited-form="inheritedFrom"
/>
</template>
32 changes: 31 additions & 1 deletion nuxt/components/scaffold-eth/debug/DebugContracts.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { getAllContracts } from '~/utils/scaffold-eth/contractsData'
const selectedContractStorageKey = 'scaffoldEthVue.selectedContract'
const contractsData = getAllContracts()
const contractNames = Object.keys(contractsData) as ContractName[]
const selectedContract = useLocalStorage(selectedContractStorageKey, contractNames[0])
</script>

<template>
Expand All @@ -13,7 +15,35 @@ const contractNames = Object.keys(contractsData) as ContractName[]
No contracts found!
</p>
<div class="flex flex-row gap-2 w-full max-w-7xl pb-1 px-6 lg:px-10 flex-wrap">
<button />
<button
v-for="contractName of contractNames"
:key="contractName"
class="btn btn-secondary btn-sm font-light hover:bg-transparent"
:class="[
selectedContract === contractName
? 'bg-base-300 hover:bg-base-300 no-animation'
: 'bg-base-100 hover:bg-secondary',
]"
@click="() => selectedContract = contractName"
>
{{ contractName }}
<span
v-if="contractsData[contractName].external"
class="tooltip tooltip-top tooltip-accent"
data-tip="External contract"
>
<Icon name="i-uil-comment-exclamation" />
</span>
</button>
</div>
<ContractUI
v-for="contractName in contractNames"
:key="contractName"
:contract-name
:class="[
contractName === selectedContract
? 'null' : 'hidden',
]"
/>
</div>
</template>
60 changes: 60 additions & 0 deletions nuxt/components/scaffold-eth/debug/DisplayTxResult.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<script setup lang="tsx">
import { type TransactionBase, type TransactionReceipt, isAddress, isHex } from 'viem'
import Address from '../Address.vue'
import NumberDisplay from './NumberDisplay.vue'
import ArrayDisplay from './ArrayDisplay.vue'
import StructDisplay from './StructDisplay.vue'
import { replacer } from '~/utils/scaffold-eth/common'
export type DisplayContent =
| string
| number
| bigint
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
| Record<string, any>
| TransactionBase
| TransactionReceipt
| undefined
| unknown
export type ResultFontSize = 'sm' | 'base' | 'xs' | 'lg' | 'xl' | '2xl' | '3xl'
const props = withDefaults(
defineProps<{
displayContent: DisplayContent | DisplayContent[]
fontSize: ResultFontSize
}>(),
{
fontSize: 'base',
},
)
function Display() {
if (props.displayContent == null) {
return ''
}
if (typeof props.displayContent === 'bigint') {
return <NumberDisplay value={props.displayContent} />
}
if (typeof props.displayContent === 'string') {
if (isAddress(props.displayContent)) {
return <Address address={props.displayContent} size={props.fontSize} />
}
if (isHex(props.displayContent)) {
return props.displayContent
}
}
if (Array.isArray(props.displayContent)) {
return <ArrayDisplay values={props.displayContent} size={props.fontSize} />
}
if (typeof props.displayContent === 'object') {
return <StructDisplay struct={props.displayContent} size={props.fontSize} />
}
return JSON.stringify(props.displayContent, replacer, 2)
}
</script>

<template>
<Display />
</template>
71 changes: 71 additions & 0 deletions nuxt/components/scaffold-eth/debug/DisplayVariable.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<script setup lang="ts">
import type { Abi, AbiFunction, Address } from 'viem'
// TODO autoimport https://github.com/wevm/wagmi/issues/3977
import { useReadContract } from '@wagmi/vue'
import { useToast } from 'vue-toastification'
import { notification } from './nitification'
import { getParsedError } from '~/utils/scaffold-eth/getParseError'
interface DisplayVariableProps {
contractAddress: Address
abiFunction: AbiFunction
refreshDisplayVariables: boolean
inheritedForm?: string
abi: Abi
}
const props = defineProps<DisplayVariableProps>()
const { targetNetwork } = useTargetNetwork()
const { data: result, isFetching, refetch, error } = useReadContract({
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
address: props.contractAddress as any,
functionName: props.abiFunction.name,
abi: props.abi,
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
chainId: targetNetwork.value.id as any,
query: {
retry: false,
},
})
const { showAnimation } = useAnimationConfig(result)
watch(() => props.refreshDisplayVariables, () => {
refetch()
})
watch(error, () => {
if (error.value) {
const parsedError = getParsedError(error)
notification.error(parsedError)
}
})
</script>

<template>
<!-- <Toast /> -->
<div class="space-y-1 pb-2">
<div class="flex items-center">
<h3 class="font-medium text-lg mb-0 break-all">
{{ abiFunction.name }}
</h3>
<button class="btn btn-ghost btn-xs">
<span v-if="isFetching" class="loading loading-spinner loading-xs" />
<Icon v-else name="i-uil-sync" class="h-3 w-3 cursor-pointer" aria-hidden="true" />
</button>
<InheritanceTooltip :inherited-form />
</div>
<div class="text-gray-500 font-medium flex flex-col items-start">
<div>
<div
class=" break-all block transition bg-transparent"
:class="[showAnimation ? 'bg-warning rounded-sm animate-pulse-fast' : '']"
>
<DisplayTxResult :display-content="result" />
</div>
</div>
</div>
</div>
</template>
14 changes: 14 additions & 0 deletions nuxt/components/scaffold-eth/debug/InheritanceTooltip.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<script setup lang="ts">
defineProps<{
inheritedForm?: string
}>()
</script>

<template>
<span
class="tooltip tooltip-top tooltip-accent px-2 md:break-normal"
:data-tip="`Inherited from: ${inheritedForm}`"
>
<Icon name="i-uil-exclamation-circle" class="w-4 h-4" />
</span>
</template>
Loading

0 comments on commit 37ed21a

Please sign in to comment.