> For the complete documentation index, see [llms.txt](https://dev.ada-anvil.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://dev.ada-anvil.io/guides/smart-contract/mint-smart-contract.md).

# Mint with Smart Contract

Simple Smart Contract - Time-locked minting with authorized signer

{% hint style="info" %}
This guide provides a practical implementation of a mint validator. For a general explanation of script purposes and validator types, see [Mint Validator](/guides/smart-contract/validators/mint-validator.md).
{% endhint %}

## Objective

* Implement a simple Aiken smart contract for minting tokens
* Demonstrate the `mint` purpose validator in action
* Implement time constraints with `validity_range`
* Require specific signers with `extra_signatories`

## Where to Find the Code

The complete example is available in the [Simple Contract repository](https://github.com/Cardano-Forge/simple-contract/tree/main).

You can follow the [README.md](https://github.com/Cardano-Forge/simple-contract/blob/main/deno/README.md) for setup instructions.

## Smart Contract Overview

This example implements a minting policy with two validation conditions:

1. **Time-lock**: Minting is restricted to transactions before a predefined expiration timestamp
2. **Authorized Signer**: Only transactions signed by a specific key can mint tokens

The contract is written in Aiken and compiled to a Plutus script that produces a CIP-57 blueprint.

## Implementation Example

### Key Components for Minting Policy Transactions

When building a transaction to mint tokens with a time-locked policy, you need to include:

1. **Mint Array**: Defines what tokens to create with their metadata
2. **Script Interactions**: Provides the redeemer needed by the validator
3. **Required Signers**: Ensures the transaction is signed by the authorized key
4. **Validity Interval**: Sets the transaction time to comply with the time-lock

### Complete Implementation

The following example demonstrates the full process of building, signing, and submitting a transaction that mints tokens with our time-locked policy:

```typescript
import { Buffer } from "node:buffer";
import { FixedTransaction, PrivateKey } from "npm:@emurgo/cardano-serialization-lib-nodejs";

// Policy hash from your deployed contract blueprint
const policyHash = "eb7bddc5b588e238d2974d544a479b6bc0dc06852b38d12308ac62e5";

// Admin key hash that is authorized to mint (from the contract)
const adminKeyHash = "a2108b5b8f1fb54abdb20c23d8ef4b8303f53bd538e1cefe91335a5d";

// Step 1: Build the transaction input
const input = {
  // Address to receive change from the transaction
  changeAddress: customer.base_address_preprod,
  
  // Optional transaction message (appears in block explorers)
  message: "Minting with time-locked policy",
  
  // Define the token to mint
  mint: [
    {
      version: "cip25",
      assetName: "MyToken001",
      policyId: policyHash,
      type: "plutus", // Indicates a Plutus script-based policy
      quantity: 1,
      metadata: {
        name: "My First Token",
        description: "A token with time-lock and signer verification",
        image: "ipfs://QmYourImageHash"
      },
    },
  ],
  
  // Provide script interaction with redeemer
  scriptInteractions: [
    {
      purpose: "mint",
      hash: policyHash,
      redeemer: {
        type: "hex",
        value: "00", // Simple redeemer for this contract (empty array in CBOR)
      },
    },
  ],
  
  // Required signer enforced by the policy
  requiredSigners: [adminKeyHash],
  
  // Time validity for the time-lock
  validityInterval: {
    // Current time in seconds (must be before the contract's deadline)
    start: Math.floor(Date.now() / 1000)
  }
};

// Step 2: Build transaction with Anvil API
const response = await fetch("https://preprod.api.ada-anvil.app/v2/services/transactions/build", {
  method: "POST",
  headers: { "x-api-key": apiKey, "Content-Type": "application/json" },
  body: JSON.stringify(input),
});

const result = await response.json();
const txToSign = result.complete;
const tx = FixedTransaction.from_bytes(Buffer.from(txToSign, "hex"));

// Step 3: Sign with both required keys (multi-signature)

// Customer signature (paying for the transaction)
tx.sign_and_add_vkey_signature(PrivateKey.from_bech32(customer.skey));

// Admin signature (required by the minting policy)
tx.sign_and_add_vkey_signature(PrivateKey.from_bech32(admin.skey));

// Step 4: Submit transaction
const submitted = await fetch("https://preprod.api.ada-anvil.app/v2/services/transactions/submit", {
  method: "POST",
  headers: { "x-api-key": apiKey, "Content-Type": "application/json" },
  body: JSON.stringify({ transaction: tx.to_hex() }),
});

const submittedResponse = await submitted.json();
console.log("Transaction ID:", submittedResponse.hash);
```

## Important Technical Details

### Transaction Validation

The transaction will only succeed if the time-lock and signature conditions are met:

{% hint style="warning" %}
The transaction must be submitted before the contract's deadline timestamp. If the current time exceeds this deadline, validation will fail and the transaction will be rejected.
{% endhint %}

### Signing the Transaction

This example requires a **multi-signature transaction** where both the customer wallet and the admin wallet must sign:

{% hint style="info" %}
**Real-World Implementation**

In production applications:

* **Customer/User signatures** would typically be handled in the frontend using wallet connectors like [Weld](https://github.com/Cardano-Forge/weld). These connectors will pass the signatures to the `transactions/submit` endpoint.
* **Admin signatures** should be applied to the transaction on a secure server.
  {% endhint %}

{% hint style="info" %}
Both signatures are required for different reasons:

1. **Customer signature**: Required because they own the inputs (UTXOs) being used to pay transaction fees
2. **Admin signature**: Required by the minting policy's `extra_signatories` condition

If either signature is missing, the transaction will fail.
{% endhint %}
