Mint & Burn Assets
Evolution-SDK provides comprehensive tools for minting and burning tokens on the Cardano blockchain, supporting native scripts and Plutus-based minting policies.
Native Script
The following is an example of how to mint tokens using a native script time-locking policy with the connected wallet as the required signer.
import {
fromText,
mintingPolicyToId,
paymentCredentialOf,
scriptFromNative,
toUnit,
unixTimeToSlot,
} from "@evolution-sdk/lucid";
async function mintWithNativeScript() {
// `lucid` has been instantiated somewhere
const address = await lucid.wallet().address();
// native script
const mintingPolicy = scriptFromNative({
type: "all",
scripts: [
{
type: "sig",
keyHash: paymentCredentialOf(address).hash, // the required signer
},
{
type: "before",
slot: unixTimeToSlot(
lucid.config().network, // "Mainnet" | "Preprod" | "Preview" | "Custom"
new Date.getTime() + 3_600_000 // 1 hour TTL
),
},
],
});
// next, we derive the Policy ID
const policyId = mintingPolicyToId(mintingPolicy);
// construct the transaction
const tx = await lucid
.newTx()
.mintAssets({
[toUnit(policyId, fromText("MyToken"))]: 1n,
[toUnit(policyId, fromText("MyOtherToken"))]: 1n,
})
.pay.ToAddress(address, {
[toUnit(policyId, fromText("MyToken"))]: 1n,
})
.validTo(new Date.getTime() + 1_800_000) // ~30 minutes
.attach.MintingPolicy(mintingPolicy)
.complete();
// sign and submit the transaction
const signed = await tx.sign.withWallet().complete();
const txHash = await signed.submit();
return txHash;
}
Plutus Script
Plutus scripts offer more flexible validation logic for minting.
import {
Constr,
Data,
fromText,
mintingPolicyToId,
toUnit,
} from "@evolution-sdk/lucid";
async function mintWithPlutusScript() {
// `lucid` has been instantiated somewhere
const address = await lucid.wallet().address();
// Plutus script
const mintingPolicy: MintingPolicy = {
type: "PlutusV3",
script: "59099a590997010000...", // CBOR hex of compiled Plutus script
};
// next, we derive the Policy ID
const policyId = mintingPolicyToId(mintingPolicy);
// token asset name
const tokenName = "MyToken";
const assetName = fromText(tokenName);
const assetUnit = toUnit(policyId, assetName);
// a redeemer must be provided when interacting with Plutus scripts
const redeemer = Data.to(
new Constr(0, [fromText("Some Redeemer")])
);
// construct the transaction
const tx = await lucid
.newTx()
.mintAssets({ [assetUnit]: 1n }, redeemer)
.attach.MintingPolicy(mintingPolicy)
.complete();
// sign and submit the transaction
const signed = await tx.sign.withWallet().complete();
const txHash = await signed.submit();
return txHash;
}
CIP-68
CIP-68 is a token standard that extends CIP-25 to provide richer metadata functionality.
import {
Constr,
Data,
fromText,
MintingPolicy,
mintingPolicyToId,
SpendingValidator,
toUnit,
validatorToAddress,
} from "@evolution-sdk/lucid";
async function mintWithCIP68() {
// `lucid` has been instantiated somewhere
const address = await lucid.wallet().address();
// token metadata fields
const tokenName = "Your Token Name";
const tokenImage = "ipfs://QmV0CID...";
// CIP-68 metadata
const metadata = Data.fromJson({
name: tokenName,
image: tokenImage,
otherFields,
});
const version = BigInt(1);
const extra: Data[] = []; // Custom user defined plutus data
const cip68 = new Constr(0, [metadata, version, extra]);
// CIP-68 utilizes datum to store the metadata
const datum = Data.to(cip68);
const redeemer = Data.void(); // Your CIP-0068 Script Redeemer
// derive a contract address to put the metadatum UTxO
const spendingValidator: SpendingValidator = { type: "PlutusV3", script: YourCip0068Script };
const validatorAddress = validatorToAddress(network, spendingValidator);
// derive the Policy ID
const mintingPolicy: MintingPolicy = { type: "PlutusV3", script: YourCip0068Script };
const policyID = mintingPolicyToId(mintingPolicy);
// reference token and user token asset names pair
const assetName = fromText(tokenName);
const refUnit = toUnit(policyID, assetName, 100); // the reference token
const usrUnit = toUnit(policyID, assetName, label); // label: 222 | 333 | 444
// construct the transaction
const tx = await lucid
.newTx()
.mintAssets(
{
[refUnit]: 1n,
[usrUnit]: BigInt(qty),
},
redeemer
)
.attach.MintingPolicy(mintingPolicy)
.pay.ToContract(
validatorAddress,
{
kind: "inline",
value: datum,
},
{
[refUnit]: 1n,
}
)
.complete();
// sign and submit the transaction
const signed = await tx.sign.withWallet().complete();
const txHash = await signed.submit();
return txHash;
}
Important Considerations
There are several considerations when minting tokens:
- Minting tokens creates them, but doesn’t automatically send them to an address, use
.pay.ToAddress()
to send the newly minted tokens to a specific address. Otherwise, it will be sent to thechange address
- All assets minted in a single
.mintAssets()
call should be of the same Policy ID - You can chain multiple
.mintAssets()
calls if you need to mint assets with different Policy IDs - The minting policy must be attached to the transaction using
.attach.MintingPolicy()
- You can also refer to a UTxO holding the reference scripts
- When using Plutus scripts, make sure to provide an appropriate redeemer
Last updated on