Mint Assets
Create a Minting Policy
First, we need to create a minting policy for the assets we want to mint. In this example, we'll use a native script time-locking policy with our wallet as the required signer:
const address = await lucid.wallet().address();
const mintingPolicy = scriptFromNative({
type: "all",
scripts: [
{ type: "sig", keyHash: paymentCredentialOf(address).hash },
{
type: "before",
slot: unixTimeToSlot(lucid.config().network, Date.now() + 1000000),
},
],
});
Next we derive the policy id from the minting policy script:
const policyId = mintingPolicyToId(mintingPolicy);
Mint Assets
Now we can mint our desired tokens:
const tx = await lucid
.newTx()
.mintAssets({
[policyId + fromText("MyToken")]: 1n,
[policyId + fromText("MyOtherToken")]: 1n,
})
.pay.ToAddress(address, { [policyId + fromText("MyToken")]: 1n })
.validTo(Date.now() + 900000)
.attach.MintingPolicy(mintingPolicy)
.complete();
const signed = await tx.sign.withWallet().complete();
const txHash = await signed.submit();
ℹ️
When working with script parameters (involving nested structures or custom data types):
const scriptWithParams = applyParamsToScript(
yourCompiledScript,
[param1, param2, ...]
);
- Minting tokens creates them, but it doesn't automatically assign them to any address. After minting, the tokens are technically "owned" by the transaction itself.
- Purpose of
pay.ToAddress()
is to send the newly minted tokens to a specific address
CIP68 Token Standard
CIP68 is a token standard that extends CIP25 to provide richer metadata functionality.
Define the CIP68 datum schema
const CIP68DatumSchema = Data.Object({
metadata: Data.Map(Data.Any(), Data.Any()),
version: Data.Integer(),
});
type CIP68DatumSchemaType = Data.Static<typeof CIP68DatumSchema>;
const CIP68Datum = CIP68DatumSchema as unknown as CIP68DatumSchemaType;
const metadataMap = new Map();
metadataMap.set(fromText("myKey"), Data.to(fromText("myValue")));
const metadataCBOR = Data.to(
{ metadata: metadataMap, version: 0n },
CIP68Datum
);
const tx = await lucid
.newTx()
.mintAssets({
[policyId + fromText("MyToken")]: 1n,
})
.pay.ToAddressWithData(
address,
{ kind: "inline", value: metadataCBOR },
{ [policyId + fromText("MyToken")]: 1n }
)
.validTo(Date.now() + 900000)
.attach.MintingPolicy(mintingPolicy)
.complete();
💡
An alternative way to define the metadata is to use an object:
const metadataObject = {
[fromText("myKey")]: Data.to(fromText("myValue"))
}
const metadataCBOR = Data.to(
{ metadata: new Map(Object.entries(metadataObject)), version: 0n },
CIP68Datum
);
Burn
To burn tokens, we use a similar process to minting, but with negative values for the assets we want to burn:
const tx = await lucid
.newTx()
.mintAssets({
[policyId + fromText("MyToken")]: -1n,
[policyId + fromText("MyOtherToken")]: -1n,
})
.validTo(Date.now() + 900000)
.attach.MintingPolicy(mintingPolicy)
.complete();
const signed = await tx.sign.withWallet().complete();
const txHash = await signed.submit();
💡
- All assets minted in a single
mintAssets
call should be of the same policy id. You can chain multiplemintAssets
calls if you need to mint assets with different policy ids - The minting policy must be attached to the transaction using
attach.MintingPolicy
- Lucid Evolution supports
Native
,PlutusV1 / V2 / V3
minting policies. The appropriate script type will be used based on the policy you attach. - When using Plutus scripts (V1 / V2 / V3), make sure to provide an appropriate redeemer.
- The
validTo
field is important for time-locked minting policies to ensure the transaction is submitted within the valid time range