Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/perfect-pianos-boil.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@wagmi/core": minor
---

Added `getPermissions` action.
5 changes: 5 additions & 0 deletions .changeset/slimy-pianos-own.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"wagmi": minor
---

Added `usePermissions` hook.
29 changes: 29 additions & 0 deletions packages/core/src/actions/getPermissions.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { config } from '@wagmi/test'
import { expect, test } from 'vitest'

import { connect } from './connect.js'
import { disconnect } from './disconnect.js'
import { getPermissions } from './getPermissions.js'

const connector = config.connectors[0]!

test('default', async () => {
await connect(config, { connector })
await expect(getPermissions(config)).resolves.toMatchInlineSnapshot(`
[
{
"caveats": [
{
"type": "filterResponse",
"value": [
"0x0c54fccd2e384b4bb6f2e405bf5cbc15a017aafb",
],
},
],
"invoker": "https://example.com",
"parentCapability": "eth_accounts",
},
]
`)
await disconnect(config, { connector })
})
46 changes: 46 additions & 0 deletions packages/core/src/actions/getPermissions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import {
type GetPermissionsErrorType as viem_GetPermissionsErrorType,
type GetPermissionsReturnType as viem_GetPermissionsReturnType,
getPermissions as viem_getPermissions,
} from 'viem/actions'

import type { Config } from '../createConfig.js'
import type { BaseErrorType, ErrorType } from '../errors/base.js'

import { getAction } from '../utils/getAction.js'
import {
type GetConnectorClientErrorType,
type GetConnectorClientParameters,
getConnectorClient,
} from './getConnectorClient.js'

export type GetPermissionsParameters<
config extends Config = Config,
chainId extends
config['chains'][number]['id'] = config['chains'][number]['id'],
> = GetConnectorClientParameters<config, chainId>

export type GetPermissionsReturnType = viem_GetPermissionsReturnType

export type GetPermissionsErrorType =
// getConnectorClient()
| GetConnectorClientErrorType
// base
| BaseErrorType
| ErrorType
// viem
| viem_GetPermissionsErrorType

/** https://wagmi.sh/core/api/actions/getPermissions */
export async function getPermissions<
config extends Config,
chainId extends config['chains'][number]['id'],
>(
config: config,
parameters: GetPermissionsParameters<config, chainId> = {},
): Promise<GetPermissionsReturnType> {
const { connector, chainId } = parameters
const client = await getConnectorClient(config, { chainId, connector })
const action = getAction(client, viem_getPermissions, 'getPermissions')
return action({})
}
22 changes: 22 additions & 0 deletions packages/core/src/connectors/mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export type MockParameters = {
| {
defaultConnected?: boolean | undefined
connectError?: boolean | Error | undefined
getPermissionsError?: boolean | Error | undefined
switchChainError?: boolean | Error | undefined
signMessageError?: boolean | Error | undefined
signTypedDataError?: boolean | Error | undefined
Expand Down Expand Up @@ -176,6 +177,27 @@ export function mock(parameters: MockParameters) {
}

// wallet methods
if (method === 'wallet_getPermissions') {
if (features.getPermissionsError) {
if (typeof features.getPermissionsError === 'boolean')
throw new UserRejectedRequestError(
new Error('Failed get permissions.'),
)
throw features.getPermissionsError
}
return [
{
invoker: 'https://example.com',
parentCapability: 'eth_accounts',
caveats: [
{
type: 'filterResponse',
value: ['0x0c54fccd2e384b4bb6f2e405bf5cbc15a017aafb'],
},
],
},
]
}
if (method === 'wallet_switchEthereumChain') {
if (features.switchChainError) {
if (typeof features.switchChainError === 'boolean')
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/exports/actions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ test('exports', () => {
"getEnsText",
"getFeeHistory",
"getGasPrice",
"getPermissions",
"getProof",
"getPublicClient",
"getStorageAt",
Expand Down
7 changes: 7 additions & 0 deletions packages/core/src/exports/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,13 @@ export {
getGasPrice,
} from '../actions/getGasPrice.js'

export {
type GetPermissionsErrorType,
type GetPermissionsParameters,
type GetPermissionsReturnType,
getPermissions,
} from '../actions/getPermissions.js'

export {
type GetProofErrorType,
type GetProofParameters,
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/exports/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ test('exports', () => {
"getEnsText",
"getFeeHistory",
"getGasPrice",
"getPermissions",
"getProof",
"getPublicClient",
"getStorageAt",
Expand Down
7 changes: 7 additions & 0 deletions packages/core/src/exports/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,13 @@ export {
getGasPrice,
} from '../actions/getGasPrice.js'

export {
type GetPermissionsErrorType,
type GetPermissionsParameters,
type GetPermissionsReturnType,
getPermissions,
} from '../actions/getPermissions.js'

export {
type GetProofErrorType,
type GetProofParameters,
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/exports/query.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ test('exports', () => {
"getFeeHistoryQueryOptions",
"getGasPriceQueryKey",
"getGasPriceQueryOptions",
"getPermissionsQueryKey",
"getPermissionsQueryOptions",
"getProofQueryKey",
"getProofQueryOptions",
"getStorageAtQueryKey",
Expand Down
9 changes: 9 additions & 0 deletions packages/core/src/exports/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,15 @@ export {
getGasPriceQueryOptions,
} from '../query/getGasPrice.js'

export {
type GetPermissionsData,
type GetPermissionsOptions,
type GetPermissionsQueryFnData,
type GetPermissionsQueryKey,
getPermissionsQueryKey,
getPermissionsQueryOptions,
} from '../query/getPermissions.js'

export {
type GetProofData,
type GetProofOptions,
Expand Down
34 changes: 34 additions & 0 deletions packages/core/src/query/getPermissions.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { chain, config } from '@wagmi/test'
import { expect, test } from 'vitest'

import { getPermissionsQueryOptions } from './getPermissions.js'

test('default', () => {
expect(getPermissionsQueryOptions(config)).toMatchInlineSnapshot(`
{
"enabled": false,
"queryFn": [Function],
"queryKey": [
"permissions",
{},
],
}
`)
})

test('parameters: chainId', () => {
expect(
getPermissionsQueryOptions(config, { chainId: chain.mainnet.id }),
).toMatchInlineSnapshot(`
{
"enabled": false,
"queryFn": [Function],
"queryKey": [
"permissions",
{
"chainId": 1,
},
],
}
`)
})
82 changes: 82 additions & 0 deletions packages/core/src/query/getPermissions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import {
type GetPermissionsErrorType,
type GetPermissionsParameters,
type GetPermissionsReturnType,
getPermissions,
} from '../actions/getPermissions.js'
import type { Config } from '../createConfig.js'
import { filterQueryOptions } from '../query/utils.js'
import type { ScopeKeyParameter } from '../types/properties.js'
import type { QueryOptions, QueryParameter } from '../types/query.js'
import type { Compute, ExactPartial } from '../types/utils.js'

export type GetPermissionsOptions<
config extends Config = Config,
chainId extends
config['chains'][number]['id'] = config['chains'][number]['id'],
selectData = GetPermissionsData,
> = Compute<
ExactPartial<GetPermissionsParameters<config, chainId>> & ScopeKeyParameter
> &
QueryParameter<
GetPermissionsQueryFnData,
GetPermissionsErrorType,
selectData,
GetPermissionsQueryKey<config, chainId>
>

export function getPermissionsQueryOptions<
config extends Config,
chainId extends config['chains'][number]['id'],
selectData = GetPermissionsData,
>(
config: config,
options: GetPermissionsOptions<config, chainId, selectData> = {},
): GetPermissionsQueryOptions<config, chainId, selectData> {
return {
...options.query,
enabled: Boolean(
options.connector?.getProvider && (options.query?.enabled ?? true),
),
queryFn: async (context) => {
if (!options.connector?.getProvider)
throw new Error('connector is required')
const [, { connectorUid: _, scopeKey: __, ...parameters }] =
context.queryKey
const permissions = await getPermissions(config, parameters)
return permissions
},
queryKey: getPermissionsQueryKey(options),
}
}

export type GetPermissionsQueryFnData = GetPermissionsReturnType

export type GetPermissionsData = GetPermissionsQueryFnData

export function getPermissionsQueryKey<
config extends Config,
chainId extends config['chains'][number]['id'],
>(
options: Compute<
ExactPartial<GetPermissionsParameters<config, chainId>> & ScopeKeyParameter
> = {},
) {
return ['permissions', filterQueryOptions(options)] as const
}

export type GetPermissionsQueryKey<
config extends Config,
chainId extends config['chains'][number]['id'],
> = ReturnType<typeof getPermissionsQueryKey<config, chainId>>

export type GetPermissionsQueryOptions<
config extends Config,
chainId extends config['chains'][number]['id'],
selectData = GetPermissionsData,
> = QueryOptions<
GetPermissionsQueryFnData,
GetPermissionsErrorType,
selectData,
GetPermissionsQueryKey<config, chainId>
>
1 change: 1 addition & 0 deletions packages/react/src/exports/actions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ test('exports', () => {
"getEnsText",
"getFeeHistory",
"getGasPrice",
"getPermissions",
"getProof",
"getPublicClient",
"getStorageAt",
Expand Down
1 change: 1 addition & 0 deletions packages/react/src/exports/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ test('exports', () => {
"useFeeHistory",
"useGasPrice",
"useInfiniteReadContracts",
"usePermissions",
"usePrepareTransactionRequest",
"useProof",
"usePublicClient",
Expand Down
6 changes: 6 additions & 0 deletions packages/react/src/exports/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,12 @@ export {
useInfiniteReadContracts,
} from '../hooks/useInfiniteReadContracts.js'

export {
type UsePermissionsParameters,
type UsePermissionsReturnType,
usePermissions,
} from '../hooks/usePermissions.js'

export {
type UsePrepareTransactionRequestParameters,
type UsePrepareTransactionRequestReturnType,
Expand Down
2 changes: 2 additions & 0 deletions packages/react/src/exports/query.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ test('exports', () => {
"getFeeHistoryQueryOptions",
"getGasPriceQueryKey",
"getGasPriceQueryOptions",
"getPermissionsQueryKey",
"getPermissionsQueryOptions",
"getProofQueryKey",
"getProofQueryOptions",
"getStorageAtQueryKey",
Expand Down
14 changes: 14 additions & 0 deletions packages/react/src/hooks/usePermissions.test-d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type { WalletPermission } from 'viem'
import { expectTypeOf, test } from 'vitest'
import { usePermissions } from './usePermissions.js'

test('select data', () => {
const result = usePermissions({
query: {
select(data) {
return data
},
},
})
expectTypeOf(result.data).toEqualTypeOf<WalletPermission[] | undefined>()
})
Loading
Loading