A collection of scripts for composable RMRK NFTs.
This repository will contain a common re-usable examples as well as real-world scripts that RMRK team actually use for production minting. We thought that sharing the actual scripts that we use can be beneficial for the community.
This project uses Hardhat with Viem instead of traditional ethers.js. You can find more information on using hardhat with viem here. This project also uses ESM instead of commonjs, which is currently not fully supported by hardhat, which uses ts-node under the hood. This experimental workaround was used to enable full ESM support in hardhat project
This project uses pnpm as package manager. You can use npm or yarn as well, but we recommend sticking with pnpm.
pnpm install
Copy .env.example
to .env
and set your environment variables as needed.
Because ESM is
an experimental feature in hardhat, we use this experimental workaround
for now to make it work, until hardhat adds a full ESM support or switches to tsx
instead of ts-node
. This also means that running hardhat scripts requires a longer command with extra arguments, therefore it is abstracted into a
script in package.json. So instead of the usual pnpm hardhat run ...
you need to run hardhat scripts
using pnpm script ...
- To avoid accidently running a script by importing something from another script, we recommend adding a code that actually runs the script in a file with
-entry.ts
prepended to it's name
// manage-contributor-entry.ts
manageContributorEntry().catch((error) => {
console.error(error);
process.exitCode = 1;
});
- For scripts that iterate through input data and send a transaction for each iteration, we strongy recommend saving transaction result logs on each iteration, rather than waiting until the loop finishes. Transaction can fail for many reasons, including running out of gas or wallet's nonce being used by another script or wallet extension while script is running. We use
ndjosn
file format to append log entry on every iteration.
// Get existing minted batches logs, or create the file if it doesn't exist
const alreadyMintedBatches = await getOrCreateNdjosnLogFile<LogEntry>(logFilePath);
for (const batchMintWithAssetsIdsInputData of batchMintWithAssetsIdsInputDataArray) {
const { contractAddress, to, assetIds } = batchMintWithAssetsIdsInputData;
const uniqueLogIdentifier = `${contractAddress}-${assetIds[0][0].toString()}-${assetIds[assetIds.length - 1][0].toString()}`;
// Check if this batch has already been minted
if (alreadyMintedBatches.find((batch) => !!batch[uniqueLogIdentifier])) {
console.warn(
`Log for this identifier already exists ${uniqueLogIdentifier}. Skipping`,
{ batchMintWithAssetsIdsInputData },
);
continue;
}
//...some transaction logic that returns hash
const logEntry: LogEntry = {
[uniqueLogIdentifier]: {
inputData: batchMintWithAssetsIdsInputData,
hash,
tokenIds,
},
};
await fs.promises.appendFile(
logFilePath,
`${jsonStringifyWithBigint(logEntry)}\n`,
);
}
See scripts/batch-mint-with-assets-ids.ts for a full example.
While this can feel like a lot of repetition for each script, this can save you a lot of time and headache when you need to resume the script after it fails in the middle of the loop and avoid having to start over again from the beginning.
The code to save transacton logs, and code that gets fields from event logs of transaction receipt should ideally be abstracted into a re-usable functions. If you wish to contribute to this project, then this is a good candidate for contribution
See scripts/mint-kanaria-base-network-campaign-rewards-entry.ts For a complete example of scripts to mint new equippable Kanaria NFTs. It consists of 4 separate scripts.
- pin metadata to ipfs using filebase sdk
- add equippable asset entries for each new equippable asset to "Kanaria Champions" kanaria items contract
- batch nest mint with asset ids from step 2 using
ItemsBatchMinter
contract.ItemsBatchMinter
is a utility contract with contributor role allowing him to mint nfts in Kanaria item contracts. We usebatchNestMintTokensWithExistingAsset
method to mint multiple NFTs in a single transaction with same assetId but different destination NFT ids, allowing NFT to be minted directly on Kanaria with new asset already added and accepted to NFTs. Please bear in mind that you won't be able to run the same scripts on Kanaria, as your private key will not have appropriate contributor role to interact with Kanaria contracts. - batch mint more NFTs directly to an account (as opposed to nest minting directly to Kanaria NFT like in step 3). Each
KanariaItems
contracts have a custom methodbatchMintWithAssets
that allows you to mint multiple NFTs each with a different (or the same) asset to a single account in a single transaction.
The entry point script scripts/mint-migration-reward-nfts-entry.ts
has multiple scripts, and you can comment required step at the bottom of the file, then comment it back and uncomment the next one, once the previous script has finished running.
pnpm script scripts/mint-migration-reward-nfts-entry.ts --network base
This repository is a work in progress. We will be adding more examples and real-world scripts as we go. Feel free to contribute with a PR. This projects structure is also coming to @rmrk-team/evm-template soon for an easy one click starter project.
- Add script to generate abis from extenral contracts using etherscan/block explorer api. See wagmi/cli for good examples of doing that
- Add deploy script examples
- Add examples of scripts for deploying and configuring RMRKCatalog contract
- Add examples of scripts for minting parent NFT with assets that reference catalog and catalog parts
- Integrate this project into upcoming
create-rmrk-evm
cli tool - Make
mint-migration-reward-nfts.ts
more generic rather than reward nft specific