# Mint with Smart Contract

{% 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 %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://dev.ada-anvil.io/guides/smart-contract/mint-smart-contract.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
