diff --git a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/_utils/getContractPageSidebarLinks.ts b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/_utils/getContractPageSidebarLinks.ts
index 474b31d404b..b147255e8f0 100644
--- a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/_utils/getContractPageSidebarLinks.ts
+++ b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/_utils/getContractPageSidebarLinks.ts
@@ -24,6 +24,12 @@ export function getContractPageSidebarLinks(data: {
       hide: !data.metadata.isModularCore,
       exactMatch: true,
     },
+    {
+      label: "Split Fees",
+      href: `${layoutPrefix}/split-fees`,
+      hide: !data.metadata.isModularCore,
+      exactMatch: true,
+    },
     {
       label: "Code Snippets",
       href: `${layoutPrefix}/code`,
diff --git a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/Claimable.tsx b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/Claimable.tsx
index 643569d6ad8..d7c820882ae 100644
--- a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/Claimable.tsx
+++ b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/Claimable.tsx
@@ -24,7 +24,7 @@ import { Separator } from "@/components/ui/separator";
 import { Skeleton } from "@/components/ui/skeleton";
 import { ToolTipLabel } from "@/components/ui/tooltip";
 import { zodResolver } from "@hookform/resolvers/zod";
-import { useMutation } from "@tanstack/react-query";
+import { useMutation, useQuery } from "@tanstack/react-query";
 import { TransactionButton } from "components/buttons/TransactionButton";
 import { addDays, fromUnixTime } from "date-fns";
 import { useAllChainsData } from "hooks/chains/allChains";
@@ -40,11 +40,13 @@ import { useFieldArray, useForm } from "react-hook-form";
 import {
   NATIVE_TOKEN_ADDRESS,
   type PreparedTransaction,
+  type ThirdwebContract,
   ZERO_ADDRESS,
   getContract,
   sendAndConfirmTransaction,
   toTokens,
 } from "thirdweb";
+import { getBytecode } from "thirdweb/contract";
 import { decimals } from "thirdweb/extensions/erc20";
 import {
   ClaimableERC20,
@@ -52,7 +54,9 @@ import {
   ClaimableERC1155,
 } from "thirdweb/modules";
 import { useActiveAccount, useReadContract } from "thirdweb/react";
+import { isContractDeployed } from "thirdweb/utils";
 import { z } from "zod";
+import ConfigureSplit from "../../split-fees/ConfigureSplitFees";
 import { addressSchema } from "../zod-schemas";
 import { CurrencySelector } from "./CurrencySelector";
 import { ModuleCardUI, type ModuleCardUIProps } from "./module-card";
@@ -71,6 +75,10 @@ export type ClaimConditionValue = {
 
 const positiveIntegerRegex = /^[0-9]\d*$/;
 
+const splitWalletBytecode =
+  "0x3d3d3d3d363d3d37363d7341dc1be6e4c7698f46268251b88b1f789aa9df265af43d3d93803e602a57fd5bf3";
+("0x3d3d3d3d363d3d37363d73207d879bae9cbf900d5e1eec04019613cedc25455af43d3d93803e602a57fd5bf3");
+
 function ClaimableModule(props: ModuleInstanceProps) {
   const { contract, ownerAccount } = props;
   const account = useActiveAccount();
@@ -108,6 +116,28 @@ function ClaimableModule(props: ModuleInstanceProps) {
     },
   );
 
+  const splitRecipientContract = getContract({
+    address: primarySaleRecipientQuery.data || "",
+    chain: contract.chain,
+    client: contract.client,
+  });
+
+  const isSplitRecipientQuery = useQuery({
+    queryKey: ["isSplitRecipient", primarySaleRecipientQuery.data],
+    queryFn: async () => {
+      if (!primarySaleRecipientQuery.data) return false;
+
+      const contractDeployed = await isContractDeployed(splitRecipientContract);
+      if (!contractDeployed) return false;
+
+      const bytecode = await getBytecode(splitRecipientContract);
+      if (bytecode !== splitWalletBytecode) return false;
+
+      return true;
+    },
+    enabled: !!primarySaleRecipientQuery.data,
+  });
+
   const noClaimConditionSet =
     claimConditionQuery.data?.availableSupply === 0n &&
     claimConditionQuery.data?.allowlistMerkleRoot ===
@@ -254,9 +284,14 @@ function ClaimableModule(props: ModuleInstanceProps) {
     <ClaimableModuleUI
       {...props}
       primarySaleRecipientSection={{
-        data: primarySaleRecipientQuery.data
-          ? { primarySaleRecipient: primarySaleRecipientQuery.data }
-          : undefined,
+        data:
+          primarySaleRecipientQuery.data && !isSplitRecipientQuery.isLoading
+            ? {
+                primarySaleRecipient: primarySaleRecipientQuery.data,
+                isSplitRecipient: isSplitRecipientQuery.data || false,
+                referenceContract: props.contract.address,
+              }
+            : undefined,
         setPrimarySaleRecipient,
       }}
       claimConditionSection={{
@@ -279,7 +314,7 @@ function ClaimableModule(props: ModuleInstanceProps) {
       }}
       isOwnerAccount={!!ownerAccount}
       name={props.contractInfo.name}
-      contractChainId={props.contract.chain.id}
+      contract={props.contract}
       setTokenId={setTokenId}
       isValidTokenId={isValidTokenId}
       noClaimConditionSet={noClaimConditionSet}
@@ -294,7 +329,7 @@ export function ClaimableModuleUI(
   props: Omit<ModuleCardUIProps, "children" | "updateButton"> & {
     isOwnerAccount: boolean;
     name: string;
-    contractChainId: number;
+    contract: ThirdwebContract;
     setTokenId: Dispatch<SetStateAction<string>>;
     isValidTokenId: boolean;
     noClaimConditionSet: boolean;
@@ -305,6 +340,8 @@ export function ClaimableModuleUI(
       data:
         | {
             primarySaleRecipient: string;
+            isSplitRecipient: boolean;
+            referenceContract: string;
           }
         | undefined;
     };
@@ -340,7 +377,7 @@ export function ClaimableModuleUI(
               <MintNFTSection
                 mint={props.mintSection.mint}
                 name={props.name}
-                contractChainId={props.contractChainId}
+                contractChainId={props.contract.chain.id}
               />
             </AccordionContent>
           </AccordionItem>
@@ -375,7 +412,7 @@ export function ClaimableModuleUI(
                     }
                     update={props.claimConditionSection.setClaimCondition}
                     name={props.name}
-                    chainId={props.contractChainId}
+                    chainId={props.contract.chain.id}
                     noClaimConditionSet={props.noClaimConditionSet}
                     currencyDecimals={
                       props.claimConditionSection.data?.currencyDecimals
@@ -409,7 +446,13 @@ export function ClaimableModuleUI(
                   update={
                     props.primarySaleRecipientSection.setPrimarySaleRecipient
                   }
-                  contractChainId={props.contractChainId}
+                  contract={props.contract}
+                  isSplitRecipient={
+                    props.primarySaleRecipientSection.data?.isSplitRecipient
+                  }
+                  referenceContract={
+                    props.primarySaleRecipientSection.data?.referenceContract
+                  }
                 />
               ) : (
                 <Skeleton className="h-[74px]" />
@@ -470,8 +513,6 @@ function ClaimConditionSection(props: {
   const { idToChain } = useAllChainsData();
   const chain = idToChain.get(props.chainId);
   const { tokenId, claimCondition } = props;
-  const [addClaimConditionButtonClicked, setAddClaimConditionButtonClicked] =
-    useState(false);
 
   const form = useForm<ClaimConditionFormValues>({
     resolver: zodResolver(claimConditionFormSchema),
@@ -544,193 +585,181 @@ function ClaimConditionSection(props: {
 
   return (
     <div className="flex flex-col gap-6">
-      {props.noClaimConditionSet && !addClaimConditionButtonClicked && (
-        <>
-          <Alert variant="warning">
-            <CircleAlertIcon className="size-5 max-sm:hidden" />
-            <AlertTitle>No Claim Condition Set</AlertTitle>
-            <AlertDescription>
-              You have not set a claim condition for this token. You can set a
-              claim condition by clicking the "Set Claim Condition" button.
-            </AlertDescription>
-          </Alert>
-
-          <Button
-            onClick={() => setAddClaimConditionButtonClicked(true)}
-            variant="outline"
-            className="w-full"
-          >
-            Add Claim Condition
-          </Button>
-        </>
+      {props.noClaimConditionSet && (
+        <Alert variant="warning">
+          <CircleAlertIcon className="size-5 max-sm:hidden" />
+          <AlertTitle>No Claim Condition Set</AlertTitle>
+          <AlertDescription>
+            You have not set a claim condition for this token. You can set a
+            claim condition by clicking the "Set Claim Condition" button.
+          </AlertDescription>
+        </Alert>
       )}
 
-      {(!props.noClaimConditionSet || addClaimConditionButtonClicked) && (
-        <Form {...form}>
-          <form onSubmit={form.handleSubmit(onSubmit)}>
-            <div className="flex flex-col gap-6">
-              <div className="grid grid-cols-1 gap-4 md:grid-cols-2">
-                <FormField
-                  control={form.control}
-                  name="pricePerToken"
-                  render={({ field }) => (
-                    <FormItem className="flex-1">
-                      <FormLabel>Price Per Token</FormLabel>
-                      <FormControl>
-                        <Input {...field} disabled={!props.isOwnerAccount} />
-                      </FormControl>
-                      <FormMessage />
-                    </FormItem>
-                  )}
-                />
+      <Form {...form}>
+        <form onSubmit={form.handleSubmit(onSubmit)}>
+          <div className="flex flex-col gap-6">
+            <div className="grid grid-cols-1 gap-4 md:grid-cols-2">
+              <FormField
+                control={form.control}
+                name="pricePerToken"
+                render={({ field }) => (
+                  <FormItem className="flex-1">
+                    <FormLabel>Price Per Token</FormLabel>
+                    <FormControl>
+                      <Input {...field} disabled={!props.isOwnerAccount} />
+                    </FormControl>
+                    <FormMessage />
+                  </FormItem>
+                )}
+              />
 
-                <FormField
-                  control={form.control}
-                  name="currencyAddress"
-                  render={({ field }) => (
-                    <FormItem>
-                      <FormLabel>Currency</FormLabel>
-                      <CurrencySelector chain={chain} field={field} />
-                    </FormItem>
-                  )}
-                />
-              </div>
+              <FormField
+                control={form.control}
+                name="currencyAddress"
+                render={({ field }) => (
+                  <FormItem>
+                    <FormLabel>Currency</FormLabel>
+                    <CurrencySelector chain={chain} field={field} />
+                  </FormItem>
+                )}
+              />
+            </div>
 
-              <div className="grid grid-cols-1 gap-4 md:grid-cols-2">
-                <FormField
-                  control={form.control}
-                  name="maxClaimableSupply"
-                  render={({ field }) => (
-                    <FormItem className="flex-1">
-                      <FormLabel>Max Available Supply</FormLabel>
-                      <FormControl>
-                        <Input {...field} disabled={!props.isOwnerAccount} />
-                      </FormControl>
-                      <FormMessage />
-                    </FormItem>
-                  )}
-                />
+            <div className="grid grid-cols-1 gap-4 md:grid-cols-2">
+              <FormField
+                control={form.control}
+                name="maxClaimableSupply"
+                render={({ field }) => (
+                  <FormItem className="flex-1">
+                    <FormLabel>Max Available Supply</FormLabel>
+                    <FormControl>
+                      <Input {...field} disabled={!props.isOwnerAccount} />
+                    </FormControl>
+                    <FormMessage />
+                  </FormItem>
+                )}
+              />
 
-                <FormField
-                  control={form.control}
-                  name="maxClaimablePerWallet"
-                  render={({ field }) => (
-                    <FormItem className="flex-1">
-                      <FormLabel>Maximum number of mints per wallet</FormLabel>
-                      <FormControl>
-                        <Input {...field} disabled={!props.isOwnerAccount} />
-                      </FormControl>
-                      <FormMessage />
-                    </FormItem>
-                  )}
+              <FormField
+                control={form.control}
+                name="maxClaimablePerWallet"
+                render={({ field }) => (
+                  <FormItem className="flex-1">
+                    <FormLabel>Maximum number of mints per wallet</FormLabel>
+                    <FormControl>
+                      <Input {...field} disabled={!props.isOwnerAccount} />
+                    </FormControl>
+                    <FormMessage />
+                  </FormItem>
+                )}
+              />
+            </div>
+
+            <FormFieldSetup
+              htmlFor="duration"
+              label="Duration"
+              isRequired
+              errorMessage={
+                form.formState.errors?.startTime?.message ||
+                form.formState.errors?.endTime?.message
+              }
+            >
+              <div>
+                <DatePickerWithRange
+                  from={startTime}
+                  to={endTime}
+                  setFrom={(from: Date) => form.setValue("startTime", from)}
+                  setTo={(to: Date) => form.setValue("endTime", to)}
                 />
               </div>
-
-              <FormFieldSetup
-                htmlFor="duration"
-                label="Duration"
-                isRequired
-                errorMessage={
-                  form.formState.errors?.startTime?.message ||
-                  form.formState.errors?.endTime?.message
-                }
-              >
-                <div>
-                  <DatePickerWithRange
-                    from={startTime}
-                    to={endTime}
-                    setFrom={(from: Date) => form.setValue("startTime", from)}
-                    setTo={(to: Date) => form.setValue("endTime", to)}
-                  />
-                </div>
-              </FormFieldSetup>
-
-              <Separator />
-
-              <div className="w-full space-y-2">
-                <FormLabel>Allowlist</FormLabel>
-                <div className="flex flex-col gap-3">
-                  {allowListFields.fields.map((fieldItem, index) => (
-                    <div className="flex items-start gap-3" key={fieldItem.id}>
-                      <FormField
-                        control={form.control}
-                        name={`allowList.${index}.address`}
-                        render={({ field }) => (
-                          <FormItem className="grow">
-                            <FormControl>
-                              <Input
-                                placeholder="0x..."
-                                {...field}
-                                disabled={!props.isOwnerAccount}
-                              />
-                            </FormControl>
-                            <FormMessage />
-                          </FormItem>
-                        )}
-                      />
-                      <ToolTipLabel label="Remove address">
-                        <Button
-                          variant="outline"
-                          className="!text-destructive-text bg-background"
-                          onClick={() => {
-                            allowListFields.remove(index);
-                          }}
-                          disabled={!props.isOwnerAccount}
-                        >
-                          <Trash2Icon className="size-4" />
-                        </Button>
-                      </ToolTipLabel>
-                    </div>
-                  ))}
-
-                  {allowListFields.fields.length === 0 && (
-                    <Alert variant="warning">
-                      <CircleAlertIcon className="size-5 max-sm:hidden" />
-                      <AlertTitle className="max-sm:!pl-0">
-                        No allowlist configured
-                      </AlertTitle>
-                    </Alert>
-                  )}
-                </div>
-
-                <div className="h-1" />
-
-                <div className="flex gap-3">
-                  <Button
-                    variant="outline"
-                    size="sm"
-                    onClick={() => {
-                      // add admin by default if adding the first input
-                      allowListFields.append({
-                        address: "",
-                      });
-                    }}
-                    className="gap-2"
-                    disabled={!props.isOwnerAccount}
-                  >
-                    <PlusIcon className="size-3" />
-                    Add Address
-                  </Button>
-                </div>
+            </FormFieldSetup>
+
+            <Separator />
+
+            <div className="w-full space-y-2">
+              <FormLabel>Allowlist</FormLabel>
+              <div className="flex flex-col gap-3">
+                {allowListFields.fields.map((fieldItem, index) => (
+                  <div className="flex items-start gap-3" key={fieldItem.id}>
+                    <FormField
+                      control={form.control}
+                      name={`allowList.${index}.address`}
+                      render={({ field }) => (
+                        <FormItem className="grow">
+                          <FormControl>
+                            <Input
+                              placeholder="0x..."
+                              {...field}
+                              disabled={!props.isOwnerAccount}
+                            />
+                          </FormControl>
+                          <FormMessage />
+                        </FormItem>
+                      )}
+                    />
+                    <ToolTipLabel label="Remove address">
+                      <Button
+                        variant="outline"
+                        className="!text-destructive-text bg-background"
+                        onClick={() => {
+                          allowListFields.remove(index);
+                        }}
+                        disabled={!props.isOwnerAccount}
+                      >
+                        <Trash2Icon className="size-4" />
+                      </Button>
+                    </ToolTipLabel>
+                  </div>
+                ))}
+
+                {allowListFields.fields.length === 0 && (
+                  <Alert variant="warning">
+                    <CircleAlertIcon className="size-5 max-sm:hidden" />
+                    <AlertTitle className="max-sm:!pl-0">
+                      No allowlist configured
+                    </AlertTitle>
+                  </Alert>
+                )}
               </div>
 
-              <div className="flex justify-end">
-                <TransactionButton
+              <div className="h-1" />
+
+              <div className="flex gap-3">
+                <Button
+                  variant="outline"
                   size="sm"
-                  className="min-w-24"
-                  disabled={updateMutation.isPending || !props.isOwnerAccount}
-                  type="submit"
-                  isPending={updateMutation.isPending}
-                  txChainID={props.chainId}
-                  transactionCount={1}
+                  onClick={() => {
+                    // add admin by default if adding the first input
+                    allowListFields.append({
+                      address: "",
+                    });
+                  }}
+                  className="gap-2"
+                  disabled={!props.isOwnerAccount}
                 >
-                  Update
-                </TransactionButton>
+                  <PlusIcon className="size-3" />
+                  Add Address
+                </Button>
               </div>
             </div>
-          </form>{" "}
-        </Form>
-      )}
+
+            <div className="flex justify-end">
+              <TransactionButton
+                size="sm"
+                className="min-w-24"
+                disabled={updateMutation.isPending || !props.isOwnerAccount}
+                type="submit"
+                isPending={updateMutation.isPending}
+                txChainID={props.chainId}
+                transactionCount={1}
+              >
+                Update
+              </TransactionButton>
+            </div>
+          </div>
+        </form>{" "}
+      </Form>
     </div>
   );
 }
@@ -747,7 +776,9 @@ function PrimarySaleRecipientSection(props: {
   primarySaleRecipient: string | undefined;
   update: (values: PrimarySaleRecipientFormValues) => Promise<void>;
   isOwnerAccount: boolean;
-  contractChainId: number;
+  isSplitRecipient?: boolean;
+  contract: ThirdwebContract;
+  referenceContract: string;
 }) {
   const form = useForm<PrimarySaleRecipientFormValues>({
     resolver: zodResolver(primarySaleRecipientFormSchema),
@@ -771,6 +802,11 @@ function PrimarySaleRecipientSection(props: {
     updateMutation.mutateAsync(form.getValues());
   };
 
+  const postSplitConfigure = async (splitWallet: string) => {
+    form.setValue("primarySaleRecipient", splitWallet);
+    await onSubmit();
+  };
+
   return (
     <Form {...form}>
       <form onSubmit={form.handleSubmit(onSubmit)}>
@@ -781,11 +817,32 @@ function PrimarySaleRecipientSection(props: {
             <FormItem className="flex-1">
               <FormLabel>Sale Recipient</FormLabel>
               <FormControl>
-                <Input
-                  placeholder="0x..."
-                  {...field}
-                  disabled={!props.isOwnerAccount}
-                />
+                <div className="flex">
+                  <Input
+                    placeholder="0x..."
+                    {...field}
+                    disabled={!props.isOwnerAccount}
+                    className={
+                      props.isOwnerAccount ? "rounded-r-none border-r-0" : ""
+                    }
+                  />
+                  {props.isOwnerAccount && (
+                    <ConfigureSplit
+                      isNewSplit={!props.isSplitRecipient}
+                      splitWallet={props.primarySaleRecipient || ""}
+                      referenceContract={props.contract}
+                      postSplitConfigure={
+                        props.isSplitRecipient ? undefined : postSplitConfigure
+                      }
+                    >
+                      <Button className="rounded-lg rounded-l-none border border-l-0 bg-foreground">
+                        {props.isSplitRecipient
+                          ? "Update Split"
+                          : "Create Split"}
+                      </Button>
+                    </ConfigureSplit>
+                  )}
+                </div>
               </FormControl>
               <FormMessage />
             </FormItem>
@@ -805,7 +862,7 @@ function PrimarySaleRecipientSection(props: {
             }
             type="submit"
             isPending={updateMutation.isPending}
-            txChainID={props.contractChainId}
+            txChainID={props.contract.chain.id}
             transactionCount={1}
           >
             Update
diff --git a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/Mintable.tsx b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/Mintable.tsx
index 32a639e2e1b..6f2d1ae1d40 100644
--- a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/Mintable.tsx
+++ b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/Mintable.tsx
@@ -6,6 +6,7 @@ import {
   AccordionTrigger,
 } from "@/components/ui/accordion";
 import { Alert, AlertTitle } from "@/components/ui/alert";
+import { Button } from "@/components/ui/button";
 import { Checkbox, CheckboxWithLabel } from "@/components/ui/checkbox";
 import {
   Form,
@@ -21,13 +22,19 @@ import { Separator } from "@/components/ui/separator";
 import { Skeleton } from "@/components/ui/skeleton";
 import { Textarea } from "@/components/ui/textarea";
 import { zodResolver } from "@hookform/resolvers/zod";
-import { useMutation } from "@tanstack/react-query";
+import { useMutation, useQuery } from "@tanstack/react-query";
 import { TransactionButton } from "components/buttons/TransactionButton";
 import { useTxNotifications } from "hooks/useTxNotifications";
 import { CircleAlertIcon } from "lucide-react";
 import { useCallback } from "react";
 import { useForm } from "react-hook-form";
-import { type PreparedTransaction, sendAndConfirmTransaction } from "thirdweb";
+import {
+  type PreparedTransaction,
+  type ThirdwebContract,
+  getContract,
+  sendAndConfirmTransaction,
+} from "thirdweb";
+import { getBytecode } from "thirdweb/contract";
 import {
   MintableERC20,
   MintableERC721,
@@ -35,9 +42,11 @@ import {
 } from "thirdweb/modules";
 import { grantRoles, hasAllRoles } from "thirdweb/modules";
 import { useReadContract } from "thirdweb/react";
+import { isContractDeployed } from "thirdweb/utils";
 import type { NFTMetadataInputLimited } from "types/modified-types";
 import { parseAttributes } from "utils/parseAttributes";
 import { z } from "zod";
+import ConfigureSplit from "../../split-fees/ConfigureSplitFees";
 import { addressSchema } from "../zod-schemas";
 import { ModuleCardUI, type ModuleCardUIProps } from "./module-card";
 import type { ModuleInstanceProps } from "./module-instance";
@@ -69,6 +78,9 @@ const isValidNft = (values: MintFormValues) =>
 
 const MINTER_ROLE = 1n;
 
+const splitWalletBytecode =
+  "0x6080604052600436106100b15760003560e01c8063f04e283e11610069578063f61510891161004e578063f615108914610163578063f7448a3114610197578063fee81cf4146101b757600080fd5b8063f04e283e1461013d578063f2fde38b1461015057600080fd5b806354d1f13d1161009a57806354d1f13d146100d3578063715018a6146100db5780638da5cb5b146100e357600080fd5b806325692962146100b65780634329db46146100c0575b600080fd5b6100be6101f8565b005b6100be6100ce366004610629565b610248565b6100be6103a9565b6100be6103e5565b3480156100ef57600080fd5b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927545b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6100be61014b36600461066b565b6103f9565b6100be61015e36600461066b565b610439565b34801561016f57600080fd5b506101137f000000000000000000000000b0293be0b3d5d5946cfa074b45d507319659c95f81565b3480156101a357600080fd5b506100be6101b236600461068d565b610460565b3480156101c357600080fd5b506101ea6101d236600461066b565b63389a75e1600c908152600091909152602090205490565b604051908152602001610134565b60006202a30067ffffffffffffffff164201905063389a75e1600c5233600052806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d600080a250565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000b0293be0b3d5d5946cfa074b45d507319659c95f16146102b7576040517f6fd1f78c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f000000000000000000000000b0293be0b3d5d5946cfa074b45d507319659c95f73ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114610331576040519150601f19603f3d011682016040523d82523d6000602084013e610336565b606091505b50509050806103a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4661696c656420746f2073656e64204574686572000000000000000000000000604482015260640160405180910390fd5b5050565b63389a75e1600c523360005260006020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92600080a2565b6103ed61058d565b6103f760006105c3565b565b61040161058d565b63389a75e1600c52806000526020600c20805442111561042957636f5e88186000526004601cfd5b60009055610436816105c3565b50565b61044161058d565b8060601b61045757637448fbae6000526004601cfd5b610436816105c3565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000b0293be0b3d5d5946cfa074b45d507319659c95f16146104cf576040517f6fd1f78c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000b0293be0b3d5d5946cfa074b45d507319659c95f811660048301526024820183905283169063a9059cbb906044016020604051808303816000875af1158015610564573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061058891906106b7565b505050565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff748739275433146103f7576382b429006000526004601cfd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927805473ffffffffffffffffffffffffffffffffffffffff9092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a355565b60006020828403121561063b57600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461066657600080fd5b919050565b60006020828403121561067d57600080fd5b61068682610642565b9392505050565b600080604083850312156106a057600080fd5b6106a983610642565b946020939093013593505050565b6000602082840312156106c957600080fd5b8151801515811461068657600080fdfea264697066735822122007cf0f59b98eb9ce1e88de58df5114d9b37a2fb3de097a3520bda4a6ac89592664736f6c634300081a0033";
+
 function MintableModule(props: ModuleInstanceProps) {
   const { contract, ownerAccount } = props;
 
@@ -86,6 +98,28 @@ function MintableModule(props: ModuleInstanceProps) {
     roles: MINTER_ROLE,
   });
 
+  const splitRecipientContract = getContract({
+    address: primarySaleRecipientQuery.data || "",
+    chain: contract.chain,
+    client: contract.client,
+  });
+
+  const isSplitRecipientQuery = useQuery({
+    queryKey: ["isSplitRecipient", primarySaleRecipientQuery.data],
+    queryFn: async () => {
+      if (!primarySaleRecipientQuery.data) return false;
+
+      const contractDeployed = await isContractDeployed(splitRecipientContract);
+      if (!contractDeployed) return false;
+
+      const bytecode = await getBytecode(splitRecipientContract);
+      if (bytecode !== splitWalletBytecode) return false;
+
+      return true;
+    },
+    enabled: !!primarySaleRecipientQuery.data,
+  });
+
   const isBatchMetadataInstalled = !!props.allModuleContractInfo.find(
     (module) => module.name.includes("BatchMetadata"),
   );
@@ -172,28 +206,32 @@ function MintableModule(props: ModuleInstanceProps) {
   return (
     <MintableModuleUI
       {...props}
-      isPending={primarySaleRecipientQuery.isPending}
+      isPending={
+        primarySaleRecipientQuery.isPending || isSplitRecipientQuery.isPending
+      }
       primarySaleRecipient={primarySaleRecipientQuery.data}
+      isSplitRecipient={isSplitRecipientQuery.data}
       updatePrimaryRecipient={update}
       mint={mint}
       isOwnerAccount={!!ownerAccount}
       name={props.contractInfo.name}
       isBatchMetadataInstalled={isBatchMetadataInstalled}
-      contractChainId={contract.chain.id}
+      contract={contract}
     />
   );
 }
 
 export function MintableModuleUI(
   props: Omit<ModuleCardUIProps, "children" | "updateButton"> & {
-    primarySaleRecipient: string | undefined;
+    primarySaleRecipient?: string | undefined;
+    isSplitRecipient?: boolean;
     isPending: boolean;
     isOwnerAccount: boolean;
     updatePrimaryRecipient: (values: UpdateFormValues) => Promise<void>;
     mint: (values: MintFormValues) => Promise<void>;
     name: string;
     isBatchMetadataInstalled: boolean;
-    contractChainId: number;
+    contract: ThirdwebContract;
   },
 ) {
   return (
@@ -215,7 +253,7 @@ export function MintableModuleUI(
                     mint={props.mint}
                     name={props.name}
                     isBatchMetadataInstalled={props.isBatchMetadataInstalled}
-                    contractChainId={props.contractChainId}
+                    contractChainId={props.contract.chain.id}
                   />
                 )}
                 {!props.isOwnerAccount && (
@@ -240,8 +278,9 @@ export function MintableModuleUI(
                 <PrimarySalesSection
                   isOwnerAccount={props.isOwnerAccount}
                   primarySaleRecipient={props.primarySaleRecipient}
+                  isSplitRecipient={props.isSplitRecipient}
                   update={props.updatePrimaryRecipient}
-                  contractChainId={props.contractChainId}
+                  contract={props.contract}
                 />
               </AccordionContent>
             </AccordionItem>
@@ -258,9 +297,10 @@ const primarySaleRecipientFormSchema = z.object({
 
 function PrimarySalesSection(props: {
   primarySaleRecipient: string | undefined;
+  isSplitRecipient?: boolean;
   update: (values: UpdateFormValues) => Promise<void>;
   isOwnerAccount: boolean;
-  contractChainId: number;
+  contract: ThirdwebContract;
 }) {
   const form = useForm<UpdateFormValues>({
     resolver: zodResolver(primarySaleRecipientFormSchema),
@@ -284,6 +324,11 @@ function PrimarySalesSection(props: {
     updateMutation.mutateAsync(form.getValues());
   };
 
+  const postSplitConfigure = async (splitWallet: string) => {
+    form.setValue("primarySaleRecipient", splitWallet);
+    await onSubmit();
+  };
+
   return (
     <Form {...form}>
       <form onSubmit={form.handleSubmit(onSubmit)}>
@@ -297,11 +342,26 @@ function PrimarySalesSection(props: {
                 sales of the assets.
               </FormDescription>
               <FormControl>
-                <Input
-                  placeholder="0x..."
-                  {...field}
-                  disabled={!props.isOwnerAccount}
-                />
+                <div className="flex">
+                  <Input
+                    placeholder="0x..."
+                    {...field}
+                    disabled={!props.isOwnerAccount}
+                    className="rounded-r-none border-r-0"
+                  />
+                  <ConfigureSplit
+                    isNewSplit={!props.isSplitRecipient}
+                    splitWallet={props.primarySaleRecipient || ""}
+                    postSplitConfigure={
+                      props.isSplitRecipient ? undefined : postSplitConfigure
+                    }
+                    referenceContract={props.contract}
+                  >
+                    <Button className="rounded-lg rounded-l-none border border-l-0 bg-foreground">
+                      {props.isSplitRecipient ? "Update Split" : "Create Split"}
+                    </Button>
+                  </ConfigureSplit>
+                </div>
               </FormControl>
               <FormMessage />
             </FormItem>
@@ -316,7 +376,7 @@ function PrimarySalesSection(props: {
             type="submit"
             isPending={updateMutation.isPending}
             transactionCount={1}
-            txChainID={props.contractChainId}
+            txChainID={props.contract.chain.id}
           >
             Update
           </TransactionButton>
diff --git a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/claimable.stories.tsx b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/claimable.stories.tsx
index fbca5b0d7f6..6eb02cf46f1 100644
--- a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/claimable.stories.tsx
+++ b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/claimable.stories.tsx
@@ -163,6 +163,7 @@ function Component() {
               ? undefined
               : {
                   primarySaleRecipient: testAddress1,
+                  isSplitRecipient: false,
                 },
             setPrimarySaleRecipient: updatePrimarySaleRecipientStub,
           }}
diff --git a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/mintable.stories.tsx b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/mintable.stories.tsx
index 35ae421e33c..4e638ef8cd3 100644
--- a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/mintable.stories.tsx
+++ b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/mintable.stories.tsx
@@ -52,6 +52,7 @@ function Component() {
   const [name, setName] = useState("MintableERC721");
   const [isBatchMetadataInstalled, setIsBatchMetadataInstalled] =
     useState(false);
+  const [isSplitRecipient, setIsSplitRecipient] = useState(false);
   async function updatePrimaryRecipientStub(values: UpdateFormValues) {
     console.log("submitting", values);
     await new Promise((resolve) => setTimeout(resolve, 1000));
@@ -101,6 +102,13 @@ function Component() {
             label="isBatchMetadataInstalled"
           />
 
+          <CheckboxWithLabel
+            value={isSplitRecipient}
+            onChange={setIsSplitRecipient}
+            id="isSplitRecipient"
+            label="isSplitRecipient"
+          />
+
           <Select value={name} onValueChange={(v) => setName(v)}>
             <SelectTrigger>
               <SelectValue />
@@ -119,6 +127,7 @@ function Component() {
             moduleAddress="0x0000000000000000000000000000000000000000"
             isPending={false}
             primarySaleRecipient={""}
+            isSplitRecipient={isSplitRecipient}
             updatePrimaryRecipient={updatePrimaryRecipientStub}
             mint={mintStub}
             uninstallButton={{
@@ -138,6 +147,7 @@ function Component() {
             moduleAddress="0x0000000000000000000000000000000000000000"
             isPending={false}
             primarySaleRecipient={testAddress1}
+            isSplitRecipient={isSplitRecipient}
             updatePrimaryRecipient={updatePrimaryRecipientStub}
             mint={mintStub}
             uninstallButton={{
@@ -157,6 +167,7 @@ function Component() {
             moduleAddress="0x0000000000000000000000000000000000000000"
             isPending={true}
             primarySaleRecipient={testAddress1}
+            isSplitRecipient={isSplitRecipient}
             updatePrimaryRecipient={updatePrimaryRecipientStub}
             mint={mintStub}
             uninstallButton={{
diff --git a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/split-fees/ClaimFeesCard.tsx b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/split-fees/ClaimFeesCard.tsx
new file mode 100644
index 00000000000..9618342dc5b
--- /dev/null
+++ b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/split-fees/ClaimFeesCard.tsx
@@ -0,0 +1,382 @@
+"use client";
+
+import { WalletAddress } from "@/components/blocks/wallet-address";
+import { CopyAddressButton } from "@/components/ui/CopyAddressButton";
+import { Spinner } from "@/components/ui/Spinner/Spinner";
+import { Button } from "@/components/ui/button";
+import {
+  Dialog,
+  DialogContent,
+  DialogDescription,
+  DialogHeader,
+  DialogTitle,
+  DialogTrigger,
+} from "@/components/ui/dialog";
+import { Form, FormField, FormItem, FormLabel } from "@/components/ui/form";
+import {
+  Table,
+  TableBody,
+  TableCell,
+  TableContainer,
+  TableHead,
+  TableHeader,
+  TableRow,
+} from "@/components/ui/table";
+import { useMutation, useQuery } from "@tanstack/react-query";
+import {
+  type ColumnDef,
+  flexRender,
+  getCoreRowModel,
+  useReactTable,
+} from "@tanstack/react-table";
+import { useAllChainsData } from "hooks/chains/allChains";
+import { useTxNotifications } from "hooks/useTxNotifications";
+import { InfoIcon } from "lucide-react";
+import { useMemo } from "react";
+import { useForm } from "react-hook-form";
+import {
+  NATIVE_TOKEN_ADDRESS,
+  type ThirdwebContract,
+  eth_getBalance,
+  getContract,
+  getRpcClient,
+  prepareContractCall,
+  readContract,
+  sendAndConfirmTransaction,
+  toEther,
+  toUnits,
+} from "thirdweb";
+import { getBalance, getCurrencyMetadata } from "thirdweb/extensions/erc20";
+import { useActiveAccount } from "thirdweb/react";
+import { CurrencySelector } from "../modules/components/CurrencySelector";
+
+export function ClaimFeesCard(props: {
+  splitWallet: string;
+  recipients: readonly string[];
+  allocations: readonly bigint[];
+  controller: string;
+  splitFeesCore: ThirdwebContract;
+}) {
+  const { idToChain } = useAllChainsData();
+  const chain = idToChain.get(props.splitFeesCore.chain.id);
+  const account = useActiveAccount();
+  const form = useForm<{ currencyAddress: string }>({
+    values: {
+      currencyAddress: NATIVE_TOKEN_ADDRESS,
+    },
+  });
+
+  const currencyAddress = form.watch("currencyAddress");
+  const currencyMetadata = useQuery({
+    queryKey: ["currencyMetadata", currencyAddress],
+    queryFn: async () => {
+      const erc20Contract = getContract({
+        address: currencyAddress,
+        client: props.splitFeesCore.client,
+        chain: props.splitFeesCore.chain,
+      });
+      return getCurrencyMetadata({
+        contract: erc20Contract,
+      });
+    },
+    enabled: currencyAddress !== NATIVE_TOKEN_ADDRESS,
+  });
+
+  const claimAmounts = useQuery({
+    queryKey: ["claimAmounts", currencyAddress],
+    queryFn: async () => {
+      const erc6909Balances = await Promise.all(
+        props.recipients.map(async (recipient) =>
+          readContract({
+            contract: props.splitFeesCore,
+            method:
+              "function balanceOf(address owner, uint256 id) returns (uint256 amount)",
+            params: [recipient, BigInt(currencyAddress)],
+          }),
+        ),
+      );
+      console.log("erc6909Balances: ", erc6909Balances);
+
+      let splitWalletBalance: bigint;
+      if (currencyAddress === NATIVE_TOKEN_ADDRESS) {
+        const rpcRequest = getRpcClient({
+          client: props.splitFeesCore.client,
+          chain: props.splitFeesCore.chain,
+        });
+        splitWalletBalance = await eth_getBalance(rpcRequest, {
+          address: props.splitWallet,
+        });
+      } else {
+        const { value } = await getBalance({
+          contract: props.splitFeesCore,
+          address: currencyAddress,
+        });
+        splitWalletBalance = value;
+      }
+      console.log("splitWalletBalance: ", splitWalletBalance);
+
+      const totalAllocation = props.allocations.reduce(
+        (acc, curr) => acc + curr,
+        0n,
+      );
+      console.log("totalAllocation: ", totalAllocation);
+      const claimAmounts = erc6909Balances.map(
+        (balance, i) =>
+          ((props.allocations[i] || 0n) * splitWalletBalance) /
+            totalAllocation +
+          balance,
+      );
+      console.log("claimAmounts: ", claimAmounts);
+
+      return claimAmounts;
+    },
+  });
+  console.log("claimAmounts: ", claimAmounts.data);
+
+  const claim = async (recipient: string) => {
+    if (!account) {
+      throw new Error("Account does not exist");
+    }
+    const splitWallet = getContract({
+      address: props.splitWallet,
+      client: props.splitFeesCore.client,
+      chain: props.splitFeesCore.chain,
+    });
+    console.log("splitWallet: ", splitWallet);
+    let splitWalletBalance: bigint;
+    if (currencyAddress === NATIVE_TOKEN_ADDRESS) {
+      const rpcRequest = getRpcClient({
+        client: props.splitFeesCore.client,
+        chain: props.splitFeesCore.chain,
+      });
+      splitWalletBalance = await eth_getBalance(rpcRequest, {
+        address: props.splitWallet,
+      });
+    } else {
+      const { value } = await getBalance({
+        contract: props.splitFeesCore,
+        address: currencyAddress,
+      });
+      splitWalletBalance = value;
+    }
+    console.log("split balance in claim: ", splitWalletBalance);
+
+    if (splitWalletBalance > 0n) {
+      const distributeTx = prepareContractCall({
+        contract: props.splitFeesCore,
+        method: "function distribute(address _splitWallet, address _token)",
+        params: [props.splitWallet, currencyAddress],
+      });
+      await sendAndConfirmTransaction({
+        account,
+        transaction: distributeTx,
+      });
+    }
+
+    const withdrawTx = prepareContractCall({
+      contract: props.splitFeesCore,
+      method: "function withdraw(address account, address _token)",
+      params: [recipient, currencyAddress],
+    });
+    await sendAndConfirmTransaction({
+      account,
+      transaction: withdrawTx,
+    });
+  };
+
+  const claimNotifications = useTxNotifications(
+    "Claim successful",
+    "Claim failed",
+  );
+  const claimMutation = useMutation({
+    mutationFn: claim,
+    onSuccess: claimNotifications.onSuccess,
+    onError: claimNotifications.onError,
+  });
+
+  const columns = useMemo<
+    ColumnDef<{ recipient: string; claimable: bigint; claim: string }>[]
+  >(
+    () => [
+      {
+        accessorKey: "recipient",
+        header: "Recipient",
+      },
+      {
+        accessorKey: "claimable",
+        header: "Claimable Amount",
+        cell: ({ row }) => {
+          if (
+            currencyAddress !== NATIVE_TOKEN_ADDRESS &&
+            !currencyMetadata.data
+          )
+            return null;
+          if (currencyAddress === NATIVE_TOKEN_ADDRESS) {
+            return <p>{toEther(row.getValue("claimable") as bigint)} ETH</p>;
+          }
+
+          return (
+            <p>
+              {toUnits(
+                row.getValue("claimable"),
+                currencyMetadata.data?.decimals || 18,
+              )}{" "}
+              {currencyMetadata.data?.symbol}
+            </p>
+          );
+        },
+      },
+      {
+        accessorKey: "claim",
+        header: "Claim",
+        cell: ({ row }) => {
+          return (
+            <Button
+              onClick={() => claimMutation.mutate(row.getValue("recipient"))}
+              disabled={
+                row.getValue("claimable") === 0n || claimMutation.isPending
+              }
+            >
+              Claim
+              {claimMutation.isPending && <Spinner className="ml-2 h-4 w-4" />}
+            </Button>
+          );
+        },
+      },
+    ],
+    [currencyAddress, currencyMetadata.data],
+  );
+
+  const data = useMemo(() => {
+    return props.recipients.map((recipient, i) => ({
+      recipient,
+      claimable: claimAmounts?.data?.[i] ?? 0n,
+      claim: "", // dummy value for react-table
+    }));
+  }, [props.recipients, claimAmounts.data]);
+
+  const table = useReactTable({
+    data,
+    columns,
+    getCoreRowModel: getCoreRowModel(),
+  });
+
+  return (
+    <section className="rounded-lg border border-border bg-muted/50">
+      {/* Header */}
+      <div className="relative p-4 lg:p-6">
+        {/* Title */}
+        <div className="pr-14">
+          <h3 className="mb-1 gap-2 font-semibold text-xl tracking-tight">
+            Split Fees
+            {/* Info Dialog */}
+            <Dialog>
+              <DialogTrigger asChild>
+                <Button
+                  variant="ghost"
+                  className="absolute top-4 right-4 h-auto w-auto p-2 text-muted-foreground"
+                >
+                  <InfoIcon className="size-5" />
+                </Button>
+              </DialogTrigger>
+              <DialogContent>
+                <DialogHeader>
+                  <DialogTitle>Split Fees Contract</DialogTitle>
+                  <DialogDescription>
+                    This contract holds the funds that are split between the
+                    recipients.
+                  </DialogDescription>
+
+                  {/* Avoid adding focus on other elements to prevent tooltips from opening on modal open */}
+                  <input className="sr-only" aria-hidden />
+
+                  <div className="h-2" />
+
+                  <div className="flex flex-col gap-4">
+                    <div>
+                      <p className="mb-1 text-muted-foreground text-sm">
+                        Split Fees
+                      </p>
+                      <CopyAddressButton
+                        className="text-xs"
+                        address={props.splitWallet}
+                        copyIconPosition="left"
+                        variant="outline"
+                      />
+                    </div>
+
+                    <div>
+                      <p className="text-muted-foreground text-sm">
+                        Controller
+                      </p>
+                      <WalletAddress address={props.controller} />
+                    </div>
+                  </div>
+                </DialogHeader>
+              </DialogContent>
+            </Dialog>
+          </h3>
+        </div>
+
+        <div className="h-2" />
+
+        <Form {...form}>
+          <form>
+            <FormField
+              control={form.control}
+              name="currencyAddress"
+              render={({ field }) => (
+                <FormItem>
+                  <FormLabel>Currency</FormLabel>
+                  <CurrencySelector chain={chain} field={field} />
+                </FormItem>
+              )}
+            />
+          </form>
+        </Form>
+
+        <div className="h-5" />
+
+        <TableContainer>
+          <Table>
+            <TableHeader>
+              {table.getHeaderGroups().map((headerGroup) => (
+                <TableRow key={headerGroup.id}>
+                  {headerGroup.headers.map((header) => {
+                    return (
+                      <TableHead key={header.id}>
+                        {header.isPlaceholder
+                          ? null
+                          : flexRender(
+                              header.column.columnDef.header,
+                              header.getContext(),
+                            )}
+                      </TableHead>
+                    );
+                  })}
+                </TableRow>
+              ))}
+            </TableHeader>
+            <TableBody>
+              {table.getRowModel().rows.map((row) => (
+                <TableRow
+                  key={row.id}
+                  data-state={row.getIsSelected() && "selected"}
+                >
+                  {row.getVisibleCells().map((cell) => (
+                    <TableCell key={cell.id}>
+                      {flexRender(
+                        cell.column.columnDef.cell,
+                        cell.getContext(),
+                      )}
+                    </TableCell>
+                  ))}
+                </TableRow>
+              ))}
+            </TableBody>
+          </Table>
+        </TableContainer>
+      </div>
+    </section>
+  );
+}
diff --git a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/split-fees/ConfigureSplitFees.tsx b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/split-fees/ConfigureSplitFees.tsx
new file mode 100644
index 00000000000..05f98b17bdc
--- /dev/null
+++ b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/split-fees/ConfigureSplitFees.tsx
@@ -0,0 +1,502 @@
+import {
+  Accordion,
+  AccordionContent,
+  AccordionItem,
+  AccordionTrigger,
+} from "@/components/ui/accordion";
+import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
+import { Button } from "@/components/ui/button";
+import {
+  Dialog,
+  DialogContent,
+  DialogDescription,
+  DialogFooter,
+  DialogHeader,
+  DialogTitle,
+  DialogTrigger,
+} from "@/components/ui/dialog";
+import {
+  Form,
+  FormControl,
+  FormField,
+  FormItem,
+  FormLabel,
+  FormMessage,
+} from "@/components/ui/form";
+import { Input } from "@/components/ui/input";
+import { ToolTipLabel } from "@/components/ui/tooltip";
+import { zodResolver } from "@hookform/resolvers/zod";
+import { useMutation } from "@tanstack/react-query";
+import { TransactionButton } from "components/buttons/TransactionButton";
+import { useTxNotifications } from "hooks/useTxNotifications";
+import { CircleAlertIcon, PlusIcon, Trash2Icon } from "lucide-react";
+import { useState } from "react";
+import { useFieldArray, useForm } from "react-hook-form";
+import {
+  type ThirdwebContract,
+  getContract,
+  parseEventLogs,
+  prepareContractCall,
+  prepareEvent,
+  sendAndConfirmTransaction,
+} from "thirdweb";
+import { useActiveAccount, useReadContract } from "thirdweb/react";
+import { z } from "zod";
+
+type Recipient = {
+  address: string;
+  percentage: string;
+};
+
+function ConfigureSplit(props: {
+  children: React.ReactNode;
+  isNewSplit?: boolean;
+  splitWallet?: string;
+  referenceContract: ThirdwebContract;
+  postSplitConfigure?: (splitWallet: string) => Promise<void> | void;
+}) {
+  const activeAccount = useActiveAccount();
+  const [open, setOpen] = useState(false);
+
+  console.log("reference contract: ", props.referenceContract);
+  const splitFeesCore = getContract({
+    address: splitFeesCoreAddress,
+    client: props.referenceContract.client,
+    chain: props.referenceContract.chain,
+  });
+  console.log("gets here");
+
+  const split = useReadContract({
+    contract: splitFeesCore,
+    method: {
+      type: "function",
+      name: "getSplit",
+      inputs: [
+        { name: "_splitWallet", type: "address", internalType: "address" },
+      ],
+      outputs: [
+        {
+          name: "",
+          type: "tuple",
+          internalType: "struct Split",
+          components: [
+            { name: "controller", type: "address", internalType: "address" },
+            {
+              name: "recipients",
+              type: "address[]",
+              internalType: "address[]",
+            },
+            {
+              name: "allocations",
+              type: "uint256[]",
+              internalType: "uint256[]",
+            },
+            {
+              name: "totalAllocation",
+              type: "uint256",
+              internalType: "uint256",
+            },
+          ],
+        },
+      ],
+      stateMutability: "view",
+    },
+    params: [props.splitWallet || ""],
+    queryOptions: {
+      enabled: !!props.splitWallet && !props.isNewSplit,
+    },
+  });
+
+  const recipients = split.data?.recipients.map((recipient, i) => ({
+    address: recipient,
+    percentage: (Number(split.data?.allocations[i]) / 100).toString(),
+  }));
+
+  const createSplit = async ({
+    recipients,
+    allocations,
+    controller,
+  }: {
+    recipients: string[];
+    allocations: bigint[];
+    controller: string;
+  }) => {
+    if (!activeAccount) {
+      throw new Error("No account or chain selected");
+    }
+
+    const splitFeesCore = getContract({
+      address: splitFeesCoreAddress,
+      client: props.referenceContract.client,
+      chain: props.referenceContract.chain,
+    });
+
+    const transaction = prepareContractCall({
+      contract: splitFeesCore,
+      method:
+        "function createSplit(address[] memory _recipients, uint256[] memory _allocations, address _controller, address _referenceContract)",
+      params: [
+        recipients,
+        allocations,
+        controller,
+        props.referenceContract.address,
+      ],
+    });
+
+    const receipt = await sendAndConfirmTransaction({
+      transaction,
+      account: activeAccount,
+    });
+    console.log("receipt for create split: ", receipt);
+
+    const decodedEvent = parseEventLogs({
+      events: [
+        prepareEvent({
+          signature:
+            "event SplitCreated(address indexed splitWallet, address[] recipients, uint256[] allocations, address controller, address referenceContract)",
+        }),
+      ],
+      logs: receipt.logs,
+    });
+    if (decodedEvent.length === 0 || !decodedEvent[0]) {
+      throw new Error(
+        `No ProxyDeployed event found in transaction: ${receipt.transactionHash}`,
+      );
+    }
+
+    if (props.postSplitConfigure) {
+      const { splitWallet } = decodedEvent[0]?.args as { splitWallet: string };
+      console.log("split wallet: ", splitWallet);
+      await props.postSplitConfigure(splitWallet);
+      console.log("post split configured");
+    }
+
+    split.refetch();
+    setOpen(false);
+  };
+
+  const updateSplit = async ({
+    recipients,
+    allocations,
+    controller,
+  }: {
+    recipients: string[];
+    allocations: bigint[];
+    controller: string;
+  }) => {
+    if (!activeAccount) {
+      throw new Error("No account selected");
+    }
+    if (!props.splitWallet) {
+      throw new Error("No split wallet selected");
+    }
+
+    console.log("gets in update split");
+
+    const splitFeesCore = getContract({
+      address: splitFeesCoreAddress,
+      client: props.referenceContract.client,
+      chain: props.referenceContract.chain,
+    });
+    console.log("split fees core: ", splitFeesCore);
+
+    const transaction = prepareContractCall({
+      contract: splitFeesCore,
+      method:
+        "function updateSplit(address _splitWallet, address[] memory _recipients, uint256[] memory _allocations, address _controller)",
+      params: [props.splitWallet, recipients, allocations, controller],
+    });
+    console.log("transaction: ", transaction);
+
+    await sendAndConfirmTransaction({
+      transaction,
+      account: activeAccount,
+    });
+    console.log("transaction sent");
+
+    if (props.postSplitConfigure) {
+      await props.postSplitConfigure("");
+      console.log("post split configured");
+    }
+
+    split.refetch();
+    setOpen(false);
+  };
+
+  return (
+    <Dialog open={open} onOpenChange={setOpen}>
+      <DialogTrigger asChild>{props.children}</DialogTrigger>
+      <DialogContent className="z-[10001]" dialogOverlayClassName="z-[10000]">
+        {activeAccount ? (
+          <ConfigureSplitUI
+            isNewSplit={props.isNewSplit}
+            activeAddress={activeAccount?.address}
+            createSplit={createSplit}
+            updateSplit={updateSplit}
+            recipients={recipients}
+            chainId={props.referenceContract.chain.id}
+          >
+            {props.children}
+          </ConfigureSplitUI>
+        ) : (
+          <Alert variant="warning">
+            <CircleAlertIcon className="size-5 max-sm:hidden" />
+            <AlertTitle>No Claim Condition Set</AlertTitle>
+            <AlertDescription>
+              You have not set a claim condition for this token. You can set a
+              claim condition by clicking the "Set Claim Condition" button.
+            </AlertDescription>
+          </Alert>
+        )}
+      </DialogContent>
+    </Dialog>
+  );
+}
+
+// TODO: place this somwhere appropriate
+const splitFeesCoreAddress = "0x640a2bb44A4c3644B416aCA8e60C67B11E41C8DF";
+
+const formSchema = z
+  .object({
+    recipients: z
+      .array(
+        z.object({
+          address: z.string().length(42, { message: "Invalid address" }),
+          percentage: z.string().refine((v) => /^\d+(\.\d{1,2})?$/.test(v), {
+            message: "Invalid percentage",
+          }),
+        }),
+      )
+      .min(2, { message: "Must have at least 2 recipients" }),
+    controller: z.string(),
+    totalAllocation: z.number(),
+  })
+  .superRefine((input, ctx) => {
+    const { recipients } = input;
+
+    if (recipients.reduce((sum, r) => sum + Number(r.percentage), 0) !== 100) {
+      ctx.addIssue({
+        code: z.ZodIssueCode.custom,
+        path: ["totalAllocation"],
+        message: "Total allocation must equal to 100%",
+      });
+    }
+  });
+
+function ConfigureSplitUI(props: {
+  children: React.ReactNode;
+  isNewSplit?: boolean;
+  activeAddress?: string;
+  createSplit: (values: {
+    recipients: string[];
+    allocations: bigint[];
+    controller: string;
+  }) => Promise<void>;
+  updateSplit: (values: {
+    recipients: string[];
+    allocations: bigint[];
+    controller: string;
+  }) => Promise<void>;
+  recipients: Recipient[] | undefined;
+  chainId: number;
+}) {
+  const form = useForm<z.infer<typeof formSchema>>({
+    resolver: zodResolver(formSchema),
+    values: {
+      controller: props.activeAddress || "",
+      recipients: props.recipients || [
+        {
+          address: props.activeAddress || "",
+          percentage: "100",
+        },
+        {
+          address: "",
+          percentage: "",
+        },
+      ],
+      // dummy field to trigger validation
+      totalAllocation: 0,
+    },
+  });
+  const formFields = useFieldArray({
+    control: form.control,
+    name: "recipients",
+  });
+
+  const createNotifications = useTxNotifications(
+    "Successfully created split",
+    "Failed to create split",
+  );
+
+  const updateNotifications = useTxNotifications(
+    "Successfully updated split",
+    "Failed to update split",
+  );
+
+  const createSplitMutation = useMutation({
+    mutationFn: props.createSplit,
+    onSuccess: createNotifications.onSuccess,
+    onError: createNotifications.onError,
+  });
+
+  const updateSplitMutation = useMutation({
+    mutationFn: props.updateSplit,
+    onSuccess: updateNotifications.onSuccess,
+    onError: updateNotifications.onError,
+  });
+
+  const onSubmit = async () => {
+    const values = form.getValues();
+    const { success } = formSchema.safeParse(values);
+    if (!success) return;
+
+    const allocations = values.recipients.map(
+      (r) => BigInt(r.percentage) * 100n,
+    );
+    console.log("allocations in submit: ", allocations);
+    const recipients = values.recipients.map((r) => r.address);
+    console.log("recipients in submit: ", recipients);
+    console.log("is new split: ", props.isNewSplit);
+    await (props.isNewSplit
+      ? createSplitMutation
+      : updateSplitMutation
+    ).mutateAsync({
+      recipients,
+      allocations,
+      controller: values.controller,
+    });
+  };
+
+  return (
+    <Form {...form}>
+      <form className="flex flex-col gap-4">
+        <DialogHeader>
+          <DialogTitle>Create Split</DialogTitle>
+          <DialogDescription>
+            The receipients assigned below will be rewarded the fees received
+            based on their allocations.
+          </DialogDescription>
+        </DialogHeader>
+
+        {formFields.fields.map((fieldItem, index) => (
+          <div className="flex items-start gap-3" key={fieldItem.id}>
+            <div className="flex gap-x-2">
+              <FormField
+                control={form.control}
+                name={`recipients.${index}.address`}
+                render={({ field }) => (
+                  <FormItem className="grow">
+                    <FormControl>
+                      <Input placeholder="Address" {...field} />
+                    </FormControl>
+                    <FormMessage />
+                  </FormItem>
+                )}
+              />
+
+              <FormField
+                control={form.control}
+                name={`recipients.${index}.percentage`}
+                render={({ field }) => (
+                  <FormItem className="grow">
+                    <FormControl>
+                      <Input
+                        type="number"
+                        placeholder="Percentage"
+                        {...field}
+                      />
+                    </FormControl>
+                    <FormMessage />
+                  </FormItem>
+                )}
+              />
+            </div>
+
+            <ToolTipLabel label="Remove address">
+              <Button
+                variant="outline"
+                className="!text-destructive-text bg-background"
+                onClick={() => {
+                  formFields.remove(index);
+                }}
+              >
+                <Trash2Icon className="size-4" />
+              </Button>
+            </ToolTipLabel>
+          </div>
+        ))}
+
+        {form.formState.errors.totalAllocation && (
+          <p className="font-medium text-destructive-text text-sm">
+            {form.formState.errors.totalAllocation.message}
+          </p>
+        )}
+
+        <div className="flex gap-3">
+          <Button
+            variant="outline"
+            size="sm"
+            onClick={() => {
+              formFields.append({
+                address: "",
+                percentage: "",
+              });
+            }}
+            className="gap-2"
+          >
+            <PlusIcon className="size-3" />
+            Add Recipient
+          </Button>
+        </div>
+
+        <Accordion type="single" collapsible className="-mx-1">
+          <AccordionItem value="metadata" className="border-none">
+            <AccordionTrigger className="border-border border-t px-1">
+              Advanced
+            </AccordionTrigger>
+            <AccordionContent className="px-1">
+              <FormField
+                control={form.control}
+                name="controller"
+                render={({ field }) => (
+                  <FormItem className="grow">
+                    <FormLabel>Controller</FormLabel>
+                    <FormControl>
+                      <Input placeholder="0x..." {...field} />
+                    </FormControl>
+                    <FormMessage />
+                  </FormItem>
+                )}
+              />
+            </AccordionContent>
+          </AccordionItem>
+        </Accordion>
+
+        <DialogFooter>
+          <TransactionButton
+            size="sm"
+            type="button"
+            onClick={form.handleSubmit(onSubmit)}
+            className="min-w-24 gap-2"
+            disabled={
+              props.isNewSplit
+                ? createSplitMutation.isPending
+                : updateSplitMutation.isPending
+            }
+            isPending={
+              props.isNewSplit
+                ? createSplitMutation.isPending
+                : updateSplitMutation.isPending
+            }
+            transactionCount={1}
+            txChainID={props.chainId}
+          >
+            {props.isNewSplit ? "Create Split" : "Update Split"}
+          </TransactionButton>
+        </DialogFooter>
+      </form>
+    </Form>
+  );
+}
+
+export default ConfigureSplit;
diff --git a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/split-fees/SplitFees.tsx b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/split-fees/SplitFees.tsx
new file mode 100644
index 00000000000..fa26c385f5e
--- /dev/null
+++ b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/split-fees/SplitFees.tsx
@@ -0,0 +1,77 @@
+"use client";
+
+import { Button } from "@/components/ui/button";
+import { TabButtons } from "@/components/ui/tabs";
+import { useState } from "react";
+import type { ThirdwebContract } from "thirdweb";
+import { ClaimFeesCard } from "./ClaimFeesCard";
+import ConfigureSplit from "./ConfigureSplitFees";
+import { SplitFeesCard } from "./SplitFeesCard";
+
+type Split = {
+  splitWallet: string;
+  recipients: readonly string[];
+  allocations: readonly bigint[];
+  controller: string;
+  referenceContract: string;
+};
+
+function SplitFees(props: {
+  splitFeesCore: ThirdwebContract;
+  splits: Split[];
+  coreContract: ThirdwebContract;
+}) {
+  const [tab, setTab] = useState<"splitFeesCard" | "claimFeesCard">(
+    "splitFeesCard",
+  );
+
+  const tabs = [
+    {
+      name: "Split Fees",
+      onClick: () => setTab("splitFeesCard"),
+      isActive: tab === "splitFeesCard",
+      isEnabled: true,
+    },
+    {
+      name: "Claim Fees",
+      onClick: () => setTab("claimFeesCard"),
+      isActive: tab === "claimFeesCard",
+      isEnabled: true,
+    },
+  ];
+
+  return (
+    <div className="flex flex-col gap-4">
+      <TabButtons tabs={tabs} />
+
+      {tab === "splitFeesCard" &&
+        props.splits.map((split) => (
+          <ClaimFeesCard
+            {...split}
+            splitFeesCore={props.splitFeesCore}
+            key={split.splitWallet}
+          />
+        ))}
+
+      {tab === "claimFeesCard" && (
+        <>
+          {props.splits.map((split) => (
+            <SplitFeesCard
+              {...split}
+              referenceContract={props.coreContract}
+              key={split.splitWallet}
+            />
+          ))}
+
+          <ConfigureSplit isNewSplit referenceContract={props.coreContract}>
+            <Button size="sm" className="self-end">
+              Create Split
+            </Button>
+          </ConfigureSplit>
+        </>
+      )}
+    </div>
+  );
+}
+
+export default SplitFees;
diff --git a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/split-fees/SplitFeesCard.tsx b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/split-fees/SplitFeesCard.tsx
new file mode 100644
index 00000000000..c22d1b5d989
--- /dev/null
+++ b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/split-fees/SplitFeesCard.tsx
@@ -0,0 +1,191 @@
+"use client";
+
+import { WalletAddress } from "@/components/blocks/wallet-address";
+import { CopyAddressButton } from "@/components/ui/CopyAddressButton";
+import { Button } from "@/components/ui/button";
+import {
+  Dialog,
+  DialogContent,
+  DialogDescription,
+  DialogHeader,
+  DialogTitle,
+  DialogTrigger,
+} from "@/components/ui/dialog";
+import {
+  Table,
+  TableBody,
+  TableCell,
+  TableContainer,
+  TableHead,
+  TableHeader,
+  TableRow,
+} from "@/components/ui/table";
+import {
+  type ColumnDef,
+  flexRender,
+  getCoreRowModel,
+  useReactTable,
+} from "@tanstack/react-table";
+import { InfoIcon } from "lucide-react";
+import { useRouter } from "next/navigation";
+import { useMemo } from "react";
+import type { ThirdwebContract } from "thirdweb";
+import { useActiveAccount } from "thirdweb/react";
+import ConfigureSplit from "./ConfigureSplitFees";
+
+export function SplitFeesCard(props: {
+  splitWallet: string;
+  recipients: readonly string[];
+  allocations: readonly bigint[];
+  controller: string;
+  referenceContract: ThirdwebContract;
+}) {
+  const account = useActiveAccount();
+  const isController = props.controller === account?.address;
+  const router = useRouter();
+
+  const columns: ColumnDef<{ allocation: number; recipient: string }>[] = [
+    {
+      accessorKey: "recipient",
+      header: "Recipient",
+    },
+    {
+      accessorKey: "allocation",
+      header: "Percentage",
+    },
+  ];
+
+  const totalAllocation = props.allocations.reduce(
+    (acc, curr) => acc + curr,
+    0n,
+  );
+  const data = useMemo(
+    () =>
+      props.recipients.map((recipient, i) => ({
+        recipient: recipient,
+        allocation:
+          (Number(props.allocations[i] || 0n) / Number(totalAllocation)) * 100,
+      })),
+    [props.recipients, props.allocations, totalAllocation],
+  );
+
+  const table = useReactTable({
+    data,
+    columns,
+    getCoreRowModel: getCoreRowModel(),
+  });
+
+  return (
+    <section className="rounded-lg border border-border bg-muted/50">
+      {/* Header */}
+      <div className="relative p-4 lg:p-6">
+        {/* Title */}
+        <div className="pr-14">
+          <h3 className="mb-1 gap-2 font-semibold text-xl tracking-tight">
+            Split Fees
+            {/* Info Dialog */}
+            <Dialog>
+              <DialogTrigger asChild>
+                <Button
+                  variant="ghost"
+                  className="absolute top-4 right-4 h-auto w-auto p-2 text-muted-foreground"
+                >
+                  <InfoIcon className="size-5" />
+                </Button>
+              </DialogTrigger>
+              <DialogContent>
+                <DialogHeader>
+                  <DialogTitle>Split Fees Contract</DialogTitle>
+                  <DialogDescription>
+                    This contract holds the funds that are split between the
+                    recipients.
+                  </DialogDescription>
+
+                  {/* Avoid adding focus on other elements to prevent tooltips from opening on modal open */}
+                  <input className="sr-only" aria-hidden />
+
+                  <div className="h-2" />
+
+                  <div className="flex flex-col gap-4">
+                    <div>
+                      <p className="mb-1 text-muted-foreground text-sm">
+                        Split Fees
+                      </p>
+                      <CopyAddressButton
+                        className="text-xs"
+                        address={props.splitWallet}
+                        copyIconPosition="left"
+                        variant="outline"
+                      />
+                    </div>
+
+                    <div>
+                      <p className="text-muted-foreground text-sm">
+                        Controller
+                      </p>
+                      <WalletAddress address={props.controller} />
+                    </div>
+                  </div>
+                </DialogHeader>
+              </DialogContent>
+            </Dialog>
+          </h3>
+        </div>
+
+        <div className="h-5" />
+
+        <TableContainer>
+          <Table>
+            <TableHeader>
+              {table.getHeaderGroups().map((headerGroup) => (
+                <TableRow key={headerGroup.id}>
+                  {headerGroup.headers.map((header) => {
+                    return (
+                      <TableHead key={header.id}>
+                        {header.isPlaceholder
+                          ? null
+                          : flexRender(
+                              header.column.columnDef.header,
+                              header.getContext(),
+                            )}
+                      </TableHead>
+                    );
+                  })}
+                </TableRow>
+              ))}
+            </TableHeader>
+            <TableBody>
+              {table.getRowModel().rows.map((row) => (
+                <TableRow
+                  key={row.id}
+                  data-state={row.getIsSelected() && "selected"}
+                >
+                  {row.getVisibleCells().map((cell) => (
+                    <TableCell key={cell.id}>
+                      {flexRender(
+                        cell.column.columnDef.cell,
+                        cell.getContext(),
+                      )}
+                    </TableCell>
+                  ))}
+                </TableRow>
+              ))}
+            </TableBody>
+          </Table>
+        </TableContainer>
+      </div>
+
+      <div className="flex flex-row justify-end gap-3 border-border border-t p-4 lg:p-6">
+        <ConfigureSplit
+          splitWallet={props.splitWallet}
+          referenceContract={props.referenceContract}
+          postSplitConfigure={(_splitWallet: string) => router.refresh()}
+        >
+          <Button size="sm" className="min-w-24 gap-2" disabled={!isController}>
+            Update
+          </Button>
+        </ConfigureSplit>
+      </div>
+    </section>
+  );
+}
diff --git a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/split-fees/page.tsx b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/split-fees/page.tsx
new file mode 100644
index 00000000000..2b2baf327f5
--- /dev/null
+++ b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/[contractAddress]/split-fees/page.tsx
@@ -0,0 +1,130 @@
+import { notFound, redirect } from "next/navigation";
+import { getContractEvents, prepareEvent, readContract } from "thirdweb";
+import { type FetchDeployMetadataResult, getContract } from "thirdweb/contract";
+import { getContractPageParamsInfo } from "../_utils/getContractFromParams";
+import { getContractPageMetadata } from "../_utils/getContractPageMetadata";
+import SplitFees from "./SplitFees";
+
+export function getModuleInstallParams(mod: FetchDeployMetadataResult) {
+  return (
+    mod.abi
+      .filter((a) => a.type === "function")
+      .find((f) => f.name === "encodeBytesOnInstall")?.inputs || []
+  );
+}
+
+// TODO: place this somwhere appropriate
+const splitFeesCoreAddress = "0x640a2bb44A4c3644B416aCA8e60C67B11E41C8DF";
+
+export default async function Page(props: {
+  params: Promise<{
+    contractAddress: string;
+    chain_id: string;
+  }>;
+}) {
+  const params = await props.params;
+  const info = await getContractPageParamsInfo(params);
+
+  if (!info) {
+    notFound();
+  }
+
+  const { contract } = info;
+
+  const { isModularCore } = await getContractPageMetadata(contract);
+
+  if (!isModularCore) {
+    redirect(`/${params.chain_id}/${params.contractAddress}`);
+  }
+  const splitFeesCore = getContract({
+    address: splitFeesCoreAddress,
+    client: contract.client,
+    chain: contract.chain,
+  });
+
+  const events = await getContractEvents({
+    contract: splitFeesCore,
+    events: [
+      prepareEvent({
+        signature:
+          "event SplitCreated(address indexed splitWallet, address[] recipients, uint256[] allocations, address controller, address referenceContract)",
+        filters: {
+          referenceContract: contract.address,
+        },
+      }),
+    ],
+    blockRange: 123456n,
+  });
+
+  const splits = await Promise.all(
+    events
+      .filter(
+        (e) =>
+          (e.args as { referenceContract: string }).referenceContract ===
+          contract.address,
+      )
+      .map(async (e) => {
+        const split = await readContract({
+          contract: splitFeesCore,
+          method: {
+            type: "function",
+            name: "getSplit",
+            inputs: [
+              {
+                name: "_splitWallet",
+                type: "address",
+                internalType: "address",
+              },
+            ],
+            outputs: [
+              {
+                name: "",
+                type: "tuple",
+                internalType: "struct Split",
+                components: [
+                  {
+                    name: "controller",
+                    type: "address",
+                    internalType: "address",
+                  },
+                  {
+                    name: "recipients",
+                    type: "address[]",
+                    internalType: "address[]",
+                  },
+                  {
+                    name: "allocations",
+                    type: "uint256[]",
+                    internalType: "uint256[]",
+                  },
+                  {
+                    name: "totalAllocation",
+                    type: "uint256",
+                    internalType: "uint256",
+                  },
+                ],
+              },
+            ],
+            stateMutability: "view",
+          },
+          params: [(e.args as { splitWallet: string }).splitWallet],
+        });
+        return {
+          splitWallet: (e.args as { splitWallet: string }).splitWallet,
+          recipients: split.recipients,
+          allocations: split.allocations,
+          controller: split.controller,
+          referenceContract: contract.address,
+        };
+      }),
+  );
+  console.log("splits: ", splits);
+
+  return (
+    <SplitFees
+      splitFeesCore={splitFeesCore}
+      splits={splits}
+      coreContract={contract}
+    />
+  );
+}
diff --git a/packages/thirdweb/src/utils/ens/namehash.ts b/packages/thirdweb/src/utils/ens/namehash.ts
index 87eb6fae7e4..fa450a83f30 100644
--- a/packages/thirdweb/src/utils/ens/namehash.ts
+++ b/packages/thirdweb/src/utils/ens/namehash.ts
@@ -20,7 +20,10 @@ export function namehash(name: string) {
     const hashed = hashFromEncodedLabel
       ? toBytes(hashFromEncodedLabel)
       : keccak256(stringToBytes(item), "bytes");
-    result = keccak256(concat([result, hashed]), "bytes");
+    result = keccak256(
+      concat([result, hashed]),
+      "bytes",
+    ) as Uint8Array<ArrayBuffer>;
   }
 
   return bytesToHex(result);