From 11e4ac0295e0c3ec0bb54be5e34c14841fe2f359 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ti=E1=BA=BFn=20Nguy=E1=BB=85n=20Kh=E1=BA=AFc?= Date: Tue, 22 Oct 2024 13:07:05 +1300 Subject: [PATCH] refactor!: remove `allowlist` & `denylist` functionality --- .changeset/friendly-files-knock.md | 6 ++ apps/docs/docs/guides/multichain.md | 70 +++++++++++++++----- packages/react/src/hooks/use-chain-id.ts | 19 +----- packages/vue/src/composables/use-chain-id.ts | 19 +----- 4 files changed, 65 insertions(+), 49 deletions(-) create mode 100644 .changeset/friendly-files-knock.md diff --git a/.changeset/friendly-files-knock.md b/.changeset/friendly-files-knock.md new file mode 100644 index 00000000..da40280e --- /dev/null +++ b/.changeset/friendly-files-knock.md @@ -0,0 +1,6 @@ +--- +"@reactive-dot/react": minor +"@reactive-dot/vue": minor +--- + +BREAKING: Removed `allowlist` and `denylist` functionality. This feature was too specific, and it’s now recommended for users to implement it as a recipe in their own applications if needed. diff --git a/apps/docs/docs/guides/multichain.md b/apps/docs/docs/guides/multichain.md index 2eda2f23..39cea36f 100644 --- a/apps/docs/docs/guides/multichain.md +++ b/apps/docs/docs/guides/multichain.md @@ -119,13 +119,13 @@ function Component() { ## Chain narrowing -By default, ReactiveDOT provides type definitions based on the merged definitions of all chains in the config. For example, if your DApp is set up to be used with Polkadot, Kusama, and Westend, the following code will not work because the Bounties pallet only exists on Polkadot and Kusama, not on Westend: +By default, ReactiveDOT merges type definitions from all the chains in the config. For instance, if your DApp is set up to work with Polkadot, Kusama, and Westend, the following code will fail because the Bounties pallet is available only on Polkadot and Kusama, not on Westend: ```tsx function Component() { - // Since `Bounties` pallet doesn't exist on Westend, this will: - // 1. Raise a TypeScript error - // 2. Throw an error during runtime if Westend is selected + // Since the `Bounties` pallet doesn't exist on Westend, this will: + // 1. Trigger a TypeScript error + // 2. Cause a runtime error if Westend is selected const bountyCount = useLazyLoadQuery((builder) => builder.readStorage("Bounties", "BountyCount", []), ); @@ -134,7 +134,7 @@ function Component() { } ``` -You have the option of either explicitly specifying the chain to query, which will override the chain ID provided via context: +To resolve this, you can explicitly specify the chain to query, which will override the chain ID provided by context: ```tsx function Component() { @@ -147,21 +147,31 @@ function Component() { } ``` -Or, to continue using the chain ID provided via context, you can use the [`useChainId`](/api/react/function/useChainId) hook along with its allowlist/denylist functionality: +Alternatively, if you want to keep using the chain ID provided by context, you can use the following pattern: ```tsx +function useBountiesChainId() { + const chainId = useChainId(); + + switch (chainId) { + case "polkadot": + case "kusama": + return chainId; + default: + throw new Error("This chain does not support bounties", { + cause: chainId, + }); + } +} + function BountiesPalletRequiredComponent() { const bountyCount = useLazyLoadQuery( (builder) => builder.readStorage("Bounties", "BountyCount", []), { - // `useChainId` with the allow/deny list will: - // 1. Throw an error if the context's chain ID conflicts with the list(s) - // 2. Restrict descriptors used by `useLazyLoadQuery` to provide correct intellisense - chainId: useChainId({ - allowlist: ["polkadot", "kusama"], - // Or - denylist: ["westend"], - }), + // This will: + // 1. Throw an error if the chain ID does not support bounties + // 2. Restrict the possible chain types for better intellisense + chainId: useBountiesChainId(), }, ); @@ -171,7 +181,7 @@ function BountiesPalletRequiredComponent() { function App() { // ... - // Only use compatible chain IDs, else an error will be thrown + // Use only compatible chain IDs, otherwise an error will be thrown const bountiesEnabledChainIds = ["polkadot", "kusama"] satisfies ChainId[]; return ( @@ -186,3 +196,33 @@ function App() { ); } ``` + +Finally, if your application primarily uses a few chains but interacts with many other supporting chains, you can use the `targetChains` option: + +```ts +import { defineConfig } from "@reactive-dot/core"; + +const config = defineConfig({ + chains: { + polkadot: { + // ... + }, + polkadot_asset_hub: { + // ... + }, + polkadot_people: { + // ... + }, + polkadot_collectives: { + // ... + }, + polkadot_bridge_hub: { + // ... + }, + }, + // This will restrict the default chain types used by hooks + // to just Polkadot when no explicit `chainId` is provided + targetChains: ["polkadot"], + // ... +}); +``` diff --git a/packages/react/src/hooks/use-chain-id.ts b/packages/react/src/hooks/use-chain-id.ts index a4c54da9..272ebc14 100644 --- a/packages/react/src/hooks/use-chain-id.ts +++ b/packages/react/src/hooks/use-chain-id.ts @@ -16,31 +16,16 @@ export function useChainIds() { /** * Hook for getting the current chain ID. * - * @param options - Additional options * @returns The current chain ID */ -export function useChainId< - const TAllowList extends ChainId[], - const TDenylist extends ChainId[] = [], ->(options?: { allowlist?: TAllowList; denylist?: TDenylist }) { +export function useChainId() { const chainId = useContext(ChainIdContext); if (chainId === undefined) { throw new ReactiveDotError("No chain ID provided"); } - if (options?.allowlist?.includes(chainId) === false) { - throw new ReactiveDotError("Chain ID not allowed", { cause: chainId }); - } - - if (options?.denylist?.includes(chainId)) { - throw new ReactiveDotError("Chain ID denied", { cause: chainId }); - } - - return chainId as Exclude< - Extract, - TDenylist[number] - >; + return chainId as ChainId; } /** diff --git a/packages/vue/src/composables/use-chain-id.ts b/packages/vue/src/composables/use-chain-id.ts index 578a7153..5f2aa145 100644 --- a/packages/vue/src/composables/use-chain-id.ts +++ b/packages/vue/src/composables/use-chain-id.ts @@ -16,13 +16,9 @@ export function useChainIds() { /** * Composable for getting the current chain ID. * - * @param options - Additional options * @returns The current chain ID */ -export function useChainId< - const TAllowList extends ChainId[], - const TDenylist extends ChainId[] = [], ->(options?: { allowlist?: TAllowList; denylist?: TDenylist }) { +export function useChainId() { const injectedChainId = inject(chainIdKey); return computed(() => { @@ -32,18 +28,7 @@ export function useChainId< throw new ReactiveDotError("No chain ID provided"); } - if (options?.allowlist?.includes(chainId) === false) { - throw new ReactiveDotError("Chain ID not allowed", { cause: chainId }); - } - - if (options?.denylist?.includes(chainId)) { - throw new ReactiveDotError("Chain ID denied", { cause: chainId }); - } - - return chainId as Exclude< - Extract, - TDenylist[number] - >; + return chainId as ChainId; }); }