Skip to content

Commit

Permalink
feat(vue): useBytecode (#4145)
Browse files Browse the repository at this point in the history
* feat: useBytecode

* docs: tweak the composable example for vue

* docs: use missing code highlighting for the TSQ Vue examples

* chore: fix tests

* chore: changeset

---------

Co-authored-by: Skas Merkushin <[email protected]>
  • Loading branch information
tmm and Skanislav committed Jul 16, 2024
1 parent 5581a81 commit b6cb147
Show file tree
Hide file tree
Showing 9 changed files with 617 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/olive-maps-knock.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@wagmi/vue": patch
---

Added `useBytecode` composable.
16 changes: 16 additions & 0 deletions packages/vue/src/composables/useBytecode.test-d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { Hex } from 'viem'
import { expectTypeOf, test } from 'vitest'

import { useBytecode } from './useBytecode.js'

test('select data', () => {
const result = useBytecode({
query: {
select(data) {
expectTypeOf(data).toEqualTypeOf<Hex | undefined>()
return data
},
},
})
expectTypeOf(result.data.value).toEqualTypeOf<Hex | undefined>()
})
296 changes: 296 additions & 0 deletions packages/vue/src/composables/useBytecode.test.ts

Large diffs are not rendered by default.

72 changes: 72 additions & 0 deletions packages/vue/src/composables/useBytecode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import type {
Config,
GetBytecodeErrorType,
ResolvedRegister,
} from '@wagmi/core'
import type { Compute } from '@wagmi/core/internal'
import {
type GetBytecodeData,
type GetBytecodeOptions,
type GetBytecodeQueryKey,
getBytecodeQueryOptions,
} from '@wagmi/core/query'
import type { GetBytecodeQueryFnData } from '@wagmi/core/query'

import type { ConfigParameter, QueryParameter } from '../types/properties.js'
import { type UseQueryReturnType, useQuery } from '../utils/query.js'

import { computed } from 'vue'
import type { DeepMaybeRef } from '../types/ref.js'
import { deepUnref } from '../utils/cloneDeep.js'
import { useChainId } from './useChainId.js'
import { useConfig } from './useConfig.js'

export type UseBytecodeParameters<
config extends Config = Config,
selectData = GetBytecodeData,
> = Compute<
DeepMaybeRef<
GetBytecodeOptions<config> &
ConfigParameter<config> &
QueryParameter<
GetBytecodeQueryFnData,
GetBytecodeErrorType,
selectData,
GetBytecodeQueryKey<config>
>
>
>

export type UseBytecodeReturnType<selectData = GetBytecodeData> =
UseQueryReturnType<selectData, GetBytecodeErrorType>

/** https://wagmi.sh/vue/api/hooks/useBytecode */
export function useBytecode<
config extends Config = ResolvedRegister['config'],
selectData = GetBytecodeData,
>(
parameters_: UseBytecodeParameters<config, selectData> = {},
): UseBytecodeReturnType<selectData> {
const parameters = computed(() => deepUnref(parameters_))

const config = useConfig(parameters)
const chainId = useChainId({ config })

const queryOptions = computed(() => {
const {
address: contractAddress,
chainId: parametersChainId,
query = {},
} = parameters.value

const options = getBytecodeQueryOptions(config, {
...parameters.value,
address: contractAddress,
chainId: parametersChainId ?? chainId.value,
})
const enabled = Boolean(contractAddress && (query.enabled ?? true))
return { ...query, ...options, enabled }
})

return useQuery(queryOptions as any) as UseBytecodeReturnType<selectData>
}
1 change: 1 addition & 0 deletions packages/vue/src/exports/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ test('exports', () => {
"useAccountEffect",
"useBalance",
"useBlockNumber",
"useBytecode",
"useChainId",
"useClient",
"useConnectorClient",
Expand Down
6 changes: 6 additions & 0 deletions packages/vue/src/exports/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ export {
useBlockNumber,
} from '../composables/useBlockNumber.js'

export {
type UseBytecodeParameters,
type UseBytecodeReturnType,
useBytecode,
} from '../composables/useBytecode.js'

export {
type UseChainIdParameters,
type UseChainIdReturnType,
Expand Down
4 changes: 4 additions & 0 deletions site/.vitepress/sidebar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,10 @@ export function getSidebar() {
text: 'useBlockNumber',
link: '/vue/api/composables/useBlockNumber',
},
{
text: 'useBytecode',
link: '/vue/api/composables/useBytecode',
},
{ text: 'useChainId', link: '/vue/api/composables/useChainId' },
{ text: 'useChains', link: '/vue/api/composables/useChains' },
{ text: 'useClient', link: '/vue/api/composables/useClient' },
Expand Down
209 changes: 209 additions & 0 deletions site/vue/api/composables/useBytecode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
---
title: useBytecode
description: Composable for retrieving the bytecode at an address.
---

<script setup>
const packageName = '@wagmi/vue'
const actionName = 'getBytecode'
const typeName = 'GetBytecode'
const TData = 'GetBytecodeData'
const TError = 'GetBytecodeErrorType'
</script>

# useBytecode

Composable for retrieving the bytecode at an address.

## Import

```ts
import { useBytecode } from '@wagmi/vue'
```

## Usage

::: code-group
```vue [index.vue]
<script setup lang="ts">
import { useBytecode } from '@wagmi/vue'
const { data: byteCode } = useBytecode({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
})
</script>
<template>
Byte Code: {{ byteCode }}
</template>
```
<<< @/snippets/react/config.ts[config.ts]
:::

## Parameters

```ts
import { type UseBytecodeParameters } from '@wagmi/vue'
```

### address

`Address | undefined`

The contract address.

::: code-group
```vue [index.vue]
<script setup lang="ts">
import { useBytecode } from '@wagmi/vue'
const { data: byteCode } = useBytecode({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2', // [!code focus]
})
</script>
<template>
Byte Code: {{ byteCode }}
</template>
```
<<< @/snippets/react/config.ts[config.ts]
:::

### blockNumber

`bigint | undefined`

The block number to check the bytecode at.

::: code-group
```vue [index.vue]
<script setup lang="ts">
import { useBytecode } from '@wagmi/vue'
const { data: byteCode } = useBytecode({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
blockNumber: 16280770n, // [!code focus]
})
</script>
<template>
Byte Code: {{ byteCode }}
</template>
```
<<< @/snippets/react/config.ts[config.ts]
:::

### blockTag

`'latest' | 'earliest' | 'pending' | 'safe' | 'finalized' | undefined`

The block tag to check the bytecode at.

::: code-group
```vue [index.vue]
<script setup lang="ts">
import { useBytecode } from '@wagmi/vue'
const { data: byteCode } = useBytecode({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
blockTag: 'safe', // [!code focus]
})
</script>
<template>
Byte Code: {{ byteCode }}
</template>
```
<<< @/snippets/react/config.ts[config.ts]
:::

### chainId

`config['chains'][number]['id'] | undefined`

The chain ID to check the bytecode at.

::: code-group
```vue [index.vue]
<script setup lang="ts">
import { useBytecode } from '@wagmi/vue'
import { mainnet } from '@wagmi/vue/chains'
const { data: byteCode } = useBytecode({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
chainId: mainnet.id, // [!code focus]
})
</script>
<template>
Byte Code: {{ byteCode }}
</template>
```
<<< @/snippets/react/config.ts[config.ts]
:::

### config

`Config | undefined`

[`Config`](/react/api/createConfig#config) to use instead of retrieving from the from nearest [`WagmiProvider`](/react/api/WagmiProvider).

::: code-group
```vue [index.vue]
<script setup lang="ts">
import { useBytecode } from '@wagmi/vue'
import { config } from './config' // [!code focus]
const { data: byteCode } = useBytecode({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
config, // [!code focus]
})
</script>
<template>
Byte Code: {{ byteCode }}
</template>
```
<<< @/snippets/react/config.ts[config.ts]
:::

### scopeKey

`string | undefined`

Scopes the cache to a given context. Hooks that have identical context will share the same cache.

::: code-group
```vue [index.vue]
<script setup lang="ts">
import { useBytecode } from '@wagmi/vue'
import { config } from './config' // [!code focus]
const { data: byteCode } = useBytecode({
address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
scopeKey: 'foo', // [!code focus]
})
</script>
<template>
Byte Code: {{ byteCode }}
</template>
```
<<< @/snippets/react/config.ts[config.ts]
:::

<!--@include: @shared/query-options.md-->

## Return Type

```ts
import { type UseBytecodeReturnType } from '@wagmi/vue'
```

<!--@include: @shared/query-result.md-->

<!--@include: @shared/query-imports.md-->

## Action

- [`getBytecode`](/core/api/actions/getBytecode)
12 changes: 8 additions & 4 deletions site/vue/guides/tanstack-query.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,16 @@ Read more about **Query Keys** on the [TanStack Query docs.](https://tanstack.co

Each Composable returns a `queryKey` value. You would use this approach when you want to utilize the query key in a Vue component as it handles reactivity for you, unlike the [Import](#import-vanilla-js) method below.

```ts
```vue [index.vue]
<script setup lang="ts">
import { useBalance } from '@wagmi/vue' // [!code hl]
function App() {
const { queryKey } = useBalance() // [!code hl]
}
const { data: balance } = useBalance() // [!code hl]
</script>
<template>
<div>{{ balance }}</div>
</template>
```

### Import (Vanilla JS)
Expand Down

0 comments on commit b6cb147

Please sign in to comment.