Skip to content

Commit

Permalink
feat: useSignMessage hook
Browse files Browse the repository at this point in the history
  • Loading branch information
ByteAtATime committed Oct 31, 2024
1 parent cda9ce7 commit e3ae569
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 0 deletions.
50 changes: 50 additions & 0 deletions packages/svelte/src/lib/hooks/useSignMessage.svelte.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { connect, disconnect, getAccount } from '@wagmi/core'
import { config, privateKey } from '@wagmi/test'
import { recoverMessageAddress } from 'viem'
import { expect, test, vi } from 'vitest'

import { privateKeyToAccount } from 'viem/accounts'
import { testHook } from './test.svelte.js'
import { useSignMessage } from './useSignMessage.svelte'

const connector = config.connectors[0]!

test(
'default',
testHook(async () => {
await connect(config, { connector })

const signMessage = $derived.by(useSignMessage())

signMessage.signMessage({ message: 'foo bar baz' })
await expect.poll(() => signMessage.isSuccess).toBeTruthy()

await expect(
recoverMessageAddress({
message: 'foo bar baz',
signature: signMessage.data!,
}),
).resolves.toEqual(getAccount(config).address)

await disconnect(config, { connector })
}),
)

test(
'behavior: local account',
testHook(async () => {
const signMessage = $derived.by(useSignMessage())

const account = privateKeyToAccount(privateKey)
signMessage.signMessage({ account, message: 'foo bar baz' })

await expect.poll(() => signMessage.isSuccess).toBeTruthy()

await expect(
recoverMessageAddress({
message: 'foo bar baz',
signature: signMessage.data!,
}),
).resolves.toEqual(account.address)
}),
)
69 changes: 69 additions & 0 deletions packages/svelte/src/lib/hooks/useSignMessage.svelte.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { createMutation } from '@tanstack/svelte-query'
import type { SignMessageErrorType } from '@wagmi/core'
import type { Compute } from '@wagmi/core/internal'
import {
type SignMessageData,
type SignMessageMutate,
type SignMessageMutateAsync,
type SignMessageVariables,
signMessageMutationOptions,
} from '@wagmi/core/query'

import type {
CreateMutationParameters,
CreateMutationReturnType,
} from '$lib/query.svelte.js'
import type { RuneParameters, RuneReturnType } from '$lib/types.js'
import type { ConfigParameter } from '../types.js'
import { useConfig } from './useConfig.svelte.js'

export type UseSignMessageParameters<context = unknown> = RuneParameters<
Compute<
ConfigParameter & {
mutation?:
| CreateMutationParameters<
SignMessageData,
SignMessageErrorType,
SignMessageVariables,
context
>
| undefined
}
>
>

export type UseSignMessageReturnType<context = unknown> = RuneReturnType<
Compute<
CreateMutationReturnType<
SignMessageData,
SignMessageErrorType,
SignMessageVariables,
context
> & {
signMessage: SignMessageMutate<context>
signMessageAsync: SignMessageMutateAsync<context>
}
>
>

/** https://wagmi.sh/react/api/hooks/useSignMessage */
export function useSignMessage<context = unknown>(
parameters: UseSignMessageParameters<context> = () => ({}),
): UseSignMessageReturnType<context> {
const { mutation } = $derived.by(parameters)

const config = $derived.by(useConfig(parameters))

const mutationOptions = $derived(signMessageMutationOptions(config))
const query = createMutation(() => ({
...mutation,
...mutationOptions,
}))
const { mutate, mutateAsync, ...result } = $derived(query)

return () => ({
...result,
signMessage: mutate,
signMessageAsync: mutateAsync,
})
}

0 comments on commit e3ae569

Please sign in to comment.