Mint with Smart Contract
Simple Smart Contract - Time-locked minting with authorized signer
Objective
Implement a simple Aiken smart contract for minting tokens
Demonstrate the
mint
purpose validator in actionImplement 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.
You can follow the README.md for setup instructions.
Smart Contract Overview
This example implements a minting policy with two validation conditions:
Time-lock: Minting is restricted to transactions before a predefined expiration timestamp
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:
Mint Array: Defines what tokens to create with their metadata
Script Interactions: Provides the redeemer needed by the validator
Required Signers: Ensures the transaction is signed by the authorized key
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:
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:
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.
Signing the Transaction
This example requires a multi-signature transaction where both the customer wallet and the admin wallet must sign:
Last updated
Was this helpful?