> ## Documentation Index
> Fetch the complete documentation index at: https://docs.namespace.ninja/llms.txt
> Use this file to discover all available pages before exploring further.

# How To Mint L1 & L2 Subnames

> Complete guide to minting ENS subnames on L1 and L2 networks using the Namespace Mint Manager SDK.

The Namespace SDK is a TypeScript library that allows developers to interact with the Namespace API and smart contracts. It abstracts the complexity of different blockchain networks and enables you to mint subnames under activated ENS names.

## Prerequisites

* **ENS Name Activation**: Your ENS name must be activated on the Namespace platform
* **Node.js**: Version 16 or higher
* **TypeScript**: Basic understanding of TypeScript
* **Web3 Knowledge**: Familiarity with Ethereum and blockchain concepts

## Getting Started

<Steps>
  <Step title="Activate Your ENS Name">
    Before you can mint subnames, your parent ENS name must be activated on the Namespace platform. This is a prerequisite for all subname minting operations.

    <Card title="How-to Activate ENS Name" icon="hat-wizard" horizontal href="/user-guide/app/activate-ens-name">
      See the step-by-step guide on how to activate an ENS Name.
    </Card>
  </Step>

  <Step title="Install Dependencies">
    Install the required packages in your TypeScript project. The SDK uses Viem under the hood for blockchain interactions.

    <CodeGroup>
      ```bash npm theme={null}
      npm install @thenamespace/mint-manager@latest viem
      ```

      ```bash yarn theme={null}
      yarn add @thenamespace/mint-manager viem
      ```
    </CodeGroup>
  </Step>

  <Step title="Configure Mint Client">
    Create and configure an instance of the MintClient with your custom RPC URLs and mint source.

    ```typescript title="mint-client.ts" theme={null}
    import {
      createMintClient,
    } from "@thenamespace/mint-manager";
    import { base } from "viem/chains";

    export const MY_ENS_NAME = "namespace.eth";
    const TOKEN = process.env.ALCHEMY_TOKEN;

    export const mintClient = createMintClient({
      customRpcUrls: { [base.id]: `https://base-mainnet.g.alchemy.com/v2/${TOKEN}` },
    });
    ```

    **Configuration Options:**

    * `customRpcUrls`: Custom RPC endpoints for different networks
    * `mintSource`: Identifier for your application (used for analytics)
  </Step>

  <Step title="Set Up Viem Clients">
    Create Viem public and wallet clients for blockchain interactions. These will handle reading blockchain state and sending transactions.

    ```typescript title="web3-client.ts" theme={null}
    import { createPublicClient, createWalletClient, http } from "viem";
    import { base } from "viem/chains";
    import { privateKeyToAccount } from "viem/accounts";

    const TOKEN = process.env.ALCHEMY_TOKEN;
    const WALLET_KEY = process.env.WALLET_PRIVATE_KEY;
    const ALCHEMY_RPC = `https://base-mainnet.g.alchemy.com/v2/${TOKEN}`;

    export const account = privateKeyToAccount(WALLET_KEY);

    export const BASE_ID = base.id;
    export const WALLET_ADDRESS = account.address;

    export const publicClient = createPublicClient({
      transport: http(ALCHEMY_RPC),
      chain: base,
    });

    export const walletClient = createWalletClient({
      transport: http(ALCHEMY_RPC),
      chain: base,
      account,
    });
    ```

    **Key Components:**

    * `publicClient`: For reading blockchain state and simulating transactions
    * `walletClient`: For signing and sending transactions
    * `wallet`: Your account instance for transaction signing
  </Step>

  <Step title="Check Subname Availability">
    Before minting, verify that your desired subname is available on the target network.

    ```typescript title="check-availability.ts" theme={null}
    import { mintClient, BASE_ID } from "./mint-client";

    const checkAvailability = async (subnameLabel: string, parentName: string) => {
      const fullName = `${subnameLabel}.${parentName}`;
      const isAvailable = await mintClient.isL2SubnameAvailable(fullName, BASE_ID);
      
      if (!isAvailable) {
        throw new Error(`${fullName} is already taken!`);
      }
      return true;
    };
    ```
  </Step>

  <Step title="Get Mint Details and Pricing">
    Retrieve detailed information about the minting process, including costs and validation checks.

    ```typescript title="get-mint-details.ts" theme={null}
    import { mintClient, WALLET_ADDRESS, MY_ENS_NAME } from "./mint-client";

    const getMintDetails = async (subnameLabel: string) => {
      const mintDetails = await mintClient.getMintDetails({
        minterAddress: WALLET_ADDRESS,
        parentName: MY_ENS_NAME,
        label: subnameLabel,
      });

      if (!mintDetails.canMint) {
        const errorMessage = mintDetails.validationErrors[0] || "Unknown reason";
        throw new Error(`Subname cannot be minted: ${errorMessage}`);
      }

      return mintDetails;
    };
    ```

    **What This Provides:**

    * Validation that the subname can be minted
    * Estimated costs (base price + network fees)
    * Any validation errors or restrictions
  </Step>

  <Step title="Generate Transaction Parameters">
    Create the transaction parameters needed to mint the subname, including any custom records you want to set.

    ```typescript title="generate-transaction.ts" theme={null}
    import { mintClient, MY_ENS_NAME } from "./mint-client";
    import { WALLET_ADDRESS } from "./web3-client";
    import { ChainName } from "@thenamespace/mint-manager";

    const generateTransaction = async (subnameLabel: string) => {
      const txParameters = await mintClient.getMintTransactionParameters({
        parentName: MY_ENS_NAME,
        label: subnameLabel,
        minterAddress: WALLET_ADDRESS,
        records: {
          texts: [
            { key: "description", value: "My awesome subname" },
            { key: "url", value: "https://example.com" },
          ],
          addresses: [
            { value: WALLET_ADDRESS, chain: ChainName.Base },
            { value: WALLET_ADDRESS, chain: ChainName.Base }
          ],
        },
      });

      return txParameters;
    };
    ```

    **Available Record Types:**

    * **Address Records**: Set wallet addresses for different chains
    * **Text Records**: Add custom metadata like descriptions, websites, social links
  </Step>

  <Step title="Simulate and Execute Transaction">
    Simulate the transaction first to ensure it will succeed, then execute it on the blockchain.

    ```typescript title="execute-mint.ts" theme={null}
    import { publicClient, walletClient, account } from "./web3-client";
    import { base } from "viem/chains";
    import { generateTransaction } from "./generate-transaction";
    import { MY_ENS_NAME } from "./mint-client";

    const executeMint = async (subnameLabel: string) => {
      try {
        // Generate transaction parameters
        const txParameters = await generateTransaction(subnameLabel);
        
        // Simulate the transaction
        const { request } = await publicClient.simulateContract({
          address: txParameters.contractAddress,
          args: txParameters.args,
          value: txParameters.value,
          account,
          functionName: txParameters.functionName,
          abi: txParameters.abi,
          chain: base,
        });

        // Execute the transaction
        const transactionHash = await walletClient.writeContract(request);
        return transactionHash;
      } catch (error) {
        console.error("Minting failed:", error);
        throw error;
      }
    };
    ```

    **Transaction Flow:**

    1. **Simulation**: Ensures the transaction will succeed before execution
    2. **Execution**: Sends the transaction to the blockchain
    3. **Confirmation**: Returns the transaction hash for tracking
  </Step>
</Steps>

## Complete Example

Here's a complete implementation that combines all the steps:

```typescript title="complete-mint-example.ts" theme={null}
import "dotenv/config";
import { createPublicClient, createWalletClient, http } from "viem";
import { base } from "viem/chains";
import { privateKeyToAccount } from "viem/accounts";
import { createMintClient, ChainName } from "@thenamespace/mint-manager";

// Parent ENS name to mint subnames under
const MY_ENS_NAME = "namespace.eth";

// Env vars (set these before running)
const ALCHEMY_TOKEN = process.env.ALCHEMY_TOKEN;
const WALLET_PRIVATE_KEY = process.env.WALLET_PRIVATE_KEY as `0x${string}`;

if (!ALCHEMY_TOKEN) {
  throw new Error("Missing ALCHEMY_TOKEN env var");
}
if (!WALLET_PRIVATE_KEY) {
  throw new Error("Missing WALLET_PRIVATE_KEY env var");
}

const ALCHEMY_RPC = `https://base-mainnet.g.alchemy.com/v2/${ALCHEMY_TOKEN}`;

const mintClient = createMintClient({
  customRpcUrls: { [base.id]: ALCHEMY_RPC },
});

// Configure viem clients
const account = privateKeyToAccount(WALLET_PRIVATE_KEY);
const publicClient = createPublicClient({ transport: http(ALCHEMY_RPC), chain: base });
const walletClient = createWalletClient({ transport: http(ALCHEMY_RPC), chain: base, account });

async function mintSubnameOnBaseMainnet(subnameLabel: string) {
  const fullName = `${subnameLabel}.${MY_ENS_NAME}`;

  // 1) Availability check (L2 on Base)
  const isAvailable = await mintClient.isL2SubnameAvailable(fullName, base.id);
  if (!isAvailable) {
    throw new Error(`${fullName} is already taken!`);
  }

  // 2) Get mint details & pricing
  const mintDetails = await mintClient.getMintDetails({
    minterAddress: account.address,
    parentName: MY_ENS_NAME,
    label: subnameLabel,
  });
  if (!mintDetails.canMint) {
    const errorMessage = mintDetails.validationErrors?.[0] || "Unknown reason";
    throw new Error(`Subname cannot be minted: ${errorMessage}`);
  }
  
  // 3) Build transaction parameters (add example records)
  const txParameters = await mintClient.getMintTransactionParameters({
    parentName: MY_ENS_NAME,
    label: subnameLabel,
    minterAddress: account.address,
    records: {
      texts: [
        { key: "description", value: "Minted with Namespace SDK" },
        { key: "url", value: "https://namespace.ninja" },
      ],
      addresses: [
        { value: account.address, chain: ChainName.Base },
      ],
    },
  });

  // 4) Simulate
  const { request } = await publicClient.simulateContract({
    address: txParameters.contractAddress,
    args: txParameters.args,
    value: txParameters.value,
    account,
    functionName: txParameters.functionName,
    abi: txParameters.abi,
    chain: base,
  });

  // 5) Execute
  const txHash = await walletClient.writeContract(request);
  console.log(`✅ Subname ${fullName} minted on Base mainnet`);
  console.log(`🔗 Tx hash: ${txHash}`);
  return { fullName, txHash };
}

async function main() {
  const labelArg = "happy"
  await mintSubnameOnBaseMainnet(labelArg);
}

main().catch((err) => {
  console.error("Minting failed:", err);
  process.exit(1);
});
```

## Environment Variables

Create a `.env` file with your configuration:

```bash theme={null}
ALCHEMY_TOKEN=your_alchemy_api_token_here
WALLET_PRIVATE_KEY=your_wallet_private_key_here
```

## Error Handling

The SDK provides comprehensive error handling for common scenarios:

* **Subname already taken**: Check availability before minting
* **Insufficient funds**: Ensure wallet has enough ETH for minting costs
* **Invalid parameters**: Validate input parameters before calling SDK methods
* **Network issues**: Handle RPC connection failures gracefully

## Next Steps

<Columns cols={2}>
  <Card title="Explore More Features" icon="rocket" href="/developer-guide/sdks/mint-manager">
    Learn about advanced minting features and customization options
  </Card>

  <Card title="View API Reference" icon="code" href="/api-reference/introduction#mint-manager-api">
    Complete API documentation for the Mint Manager SDK
  </Card>
</Columns>
