[Extensions] Expose permission detection logic (#4375)

### TL;DR

Exposed permission detection logic for the Extensions module.

### What changed?

- Added `is*Supported` functions for various permission-related operations.
- Exported these new functions to make them accessible to users.
- Implemented `isGetAllRoleMembersSupported` function to check if both `getRoleMember` and `getRoleMemberCount` are supported.
- Renamed `grant.ts` to `grantRole.ts` for consistency.

### How to test?

1. Import the new `is*Supported` functions from the permissions module.
2. Pass an array of contract function selectors to these functions.
3. Verify that they correctly identify whether the corresponding permission operations are supported.

Example:
```typescript
import { isGetAllRoleMembersSupported } from "thirdweb/extensions/permissions";

const supported = isGetAllRoleMembersSupported(["0x..."]);
console.log("getAllRoleMembers supported:", supported);
```

### Why make this change?

This change allows developers to programmatically detect which permission-related operations are supported by a given contract. This is particularly useful when working with contracts that may implement only a subset of the permissions interface, enabling more robust and flexible integration with various smart contracts.

---

<!-- start pr-codex -->

---

## PR-Codex overview
This PR enhances the `thirdweb` package by exposing permission detection logic for various role-related operations.

### Detailed summary
- Exposes permission detection logic for `hasRole`, `revokeRole`, `getRoleAdmin`, `renounceRole`, and more
- Renamed `grant.js` to `grantRole.js`
- Added new exports for supported permission operations
- Added a new function `isGetAllRoleMembersSupported` to check support for `getAllRoleMembers` operation

> ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}`

<!-- end pr-codex -->
This commit is contained in:
jnsdls
2024-09-04 06:56:14 +00:00
parent ccaaef481c
commit edb95d00ca
11 changed files with 59 additions and 4 deletions
+5
View File
@@ -0,0 +1,5 @@
---
"thirdweb": patch
---
[Extensions] expose permission detection logic
@@ -6,24 +6,29 @@
export {
hasRole,
type HasRoleParams,
isHasRoleSupported,
} from "../../extensions/permissions/read/hasRole.js";
export {
getRoleAdmin,
type GetRoleAdminParams,
isGetRoleAdminSupported,
} from "../../extensions/permissions/read/getRoleAdmin.js";
// WRITE
export {
grantRole,
type GrantRoleParams,
} from "../../extensions/permissions/write/grant.js";
isGrantRoleSupported,
} from "../../extensions/permissions/write/grantRole.js";
export {
revokeRole,
type RevokeRoleParams,
isRevokeRoleSupported,
} from "../../extensions/permissions/write/revokeRole.js";
export {
renounceRole,
type RenounceRoleParams,
isRenounceRoleSupported,
} from "../../extensions/permissions/write/renounceRole.js";
// EVENTS
@@ -48,14 +53,17 @@ export {
export {
getRoleMember,
type GetRoleMemberParams,
isGetRoleMemberSupported,
} from "../../extensions/permissions/read/getRoleMember.js";
export {
getRoleMemberCount,
type GetRoleMemberCountParams,
isGetRoleMemberCountSupported,
} from "../../extensions/permissions/read/getRoleMemberCount.js";
export {
getAllRoleMembers,
type GetAllRoleMembersParams,
isGetAllRoleMembersSupported,
} from "../../extensions/permissions/read/getAllMembers.js";
// --------------------------------------------------------
@@ -10,7 +10,7 @@ import { sendAndConfirmTransaction } from "../../transaction/actions/send-and-co
import { deployERC20Contract } from "../prebuilts/deploy-erc20.js";
import { getAllRoleMembers } from "./read/getAllMembers.js";
import { hasRole } from "./read/hasRole.js";
import { grantRole } from "./write/grant.js";
import { grantRole } from "./write/grantRole.js";
import { revokeRole } from "./write/revokeRole.js";
describe.runIf(process.env.TW_SECRET_KEY)("Permissions", () => {
@@ -1,6 +1,12 @@
import type { BaseTransactionOptions } from "../../../transaction/types.js";
import { getRoleMember } from "../__generated__/IPermissionsEnumerable/read/getRoleMember.js";
import { getRoleMemberCount } from "../__generated__/IPermissionsEnumerable/read/getRoleMemberCount.js";
import {
getRoleMember,
isGetRoleMemberSupported,
} from "../__generated__/IPermissionsEnumerable/read/getRoleMember.js";
import {
getRoleMemberCount,
isGetRoleMemberCountSupported,
} from "../__generated__/IPermissionsEnumerable/read/getRoleMemberCount.js";
import { type RoleInput, getRoleHash } from "../utils.js";
/**
@@ -47,3 +53,25 @@ export async function getAllRoleMembers(
return Promise.all(promises);
}
/**
* Checks if the `getAllRoleMembers` method is supported by the given contract.
* @param availableSelectors An array of 4byte function selectors of the contract. You can get this in various ways, such as using "whatsabi" or if you have the ABI of the contract available you can use it to generate the selectors.
* @returns A boolean indicating if the `getAllRoleMembers` method is supported.
* @extension PERMISSIONS
* @example
* ```ts
* import { isGetAllRoleMembersSupported } from "thirdweb/extensions/permissions";
*
* const supported = isGetAllRoleMembersSupported(["0x..."]);
* ```
*/
export function isGetAllRoleMembersSupported(
availableSelectors: string[],
): boolean {
// both need to be supported to get all members
return (
isGetRoleMemberSupported(availableSelectors) &&
isGetRoleMemberCountSupported(availableSelectors)
);
}
@@ -2,6 +2,8 @@ import type { BaseTransactionOptions } from "../../../transaction/types.js";
import { getRoleAdmin as generatedGetRoleAdmin } from "../__generated__/IPermissions/read/getRoleAdmin.js";
import { type RoleInput, getRoleHash } from "../utils.js";
export { isGetRoleAdminSupported } from "../__generated__/IPermissions/read/getRoleAdmin.js";
/**
* @extension PERMISSIONS
*/
@@ -2,6 +2,8 @@ import type { BaseTransactionOptions } from "../../../transaction/types.js";
import { getRoleMember as generatedGetRoleMember } from "../__generated__/IPermissionsEnumerable/read/getRoleMember.js";
import { type RoleInput, getRoleHash } from "../utils.js";
export { isGetRoleMemberSupported } from "../__generated__/IPermissionsEnumerable/read/getRoleMember.js";
/**
* @extension PERMISSIONS
*/
@@ -2,6 +2,8 @@ import type { BaseTransactionOptions } from "../../../transaction/types.js";
import { getRoleMemberCount as generatedGetRoleMemberCount } from "../__generated__/IPermissionsEnumerable/read/getRoleMemberCount.js";
import { type RoleInput, getRoleHash } from "../utils.js";
export { isGetRoleMemberCountSupported } from "../__generated__/IPermissionsEnumerable/read/getRoleMemberCount.js";
/**
* @extension PERMISSIONS
*/
@@ -2,6 +2,8 @@ import type { BaseTransactionOptions } from "../../../transaction/types.js";
import { hasRole as hasRoleGenerated } from "../__generated__/IPermissions/read/hasRole.js";
import { type RoleInput, getRoleHash } from "../utils.js";
export { isHasRoleSupported } from "../__generated__/IPermissions/read/hasRole.js";
/**
* @extension PERMISSIONS
*/
@@ -3,6 +3,8 @@ import type { BaseTransactionOptions } from "../../../transaction/types.js";
import { grantRole as generatedGrantRole } from "../__generated__/IPermissions/write/grantRole.js";
import { type RoleInput, getRoleHash } from "../utils.js";
export { isGrantRoleSupported } from "../__generated__/IPermissions/write/grantRole.js";
/**
* @extension PERMISSIONS
*/
@@ -3,6 +3,8 @@ import type { BaseTransactionOptions } from "../../../transaction/types.js";
import { renounceRole as generatedRenounceRole } from "../__generated__/IPermissions/write/renounceRole.js";
import { type RoleInput, getRoleHash } from "../utils.js";
export { isRenounceRoleSupported } from "../__generated__/IPermissions/write/renounceRole.js";
/**
* @extension PERMISSIONS
*/
@@ -3,6 +3,8 @@ import type { BaseTransactionOptions } from "../../../transaction/types.js";
import { revokeRole as generatedRevokeRole } from "../__generated__/IPermissions/write/revokeRole.js";
import { type RoleInput, getRoleHash } from "../utils.js";
export { isRevokeRoleSupported } from "../__generated__/IPermissions/write/revokeRole.js";
/**
* @extension PERMISSIONS
*/