diff --git a/cli-typescript/src/abis/index.ts b/cli-typescript/src/abis/index.ts index 2da6f29b..48295402 100644 --- a/cli-typescript/src/abis/index.ts +++ b/cli-typescript/src/abis/index.ts @@ -75,6 +75,7 @@ export const NEW_CONTRACT_INITIALIZED_EVENT_ABI = { { name: 'standardId', type: 'uint8' }, { name: 'name', type: 'string' }, { name: 'symbol', type: 'string' }, + { name: 'mintFee', type: 'uint256' }, ], } as const; @@ -142,6 +143,20 @@ export const TRANSFER_OWNERSHIP_ABI = { type: 'function', } as const; +export const SET_MINT_FEE_ABI = { + inputs: [ + { + internalType: 'uint256', + name: 'mintFee', + type: 'uint256', + }, + ], + name: 'setMintFee', + outputs: [], + stateMutability: 'nonpayable', + type: 'function', +} as const; + export const ERC712M_ABIS = { setup: { type: 'function', @@ -253,11 +268,6 @@ export const ERC712M_ABIS = { name: 'price', type: 'uint80', }, - { - internalType: 'uint80', - name: 'mintFee', - type: 'uint80', - }, { internalType: 'uint32', name: 'walletLimit', @@ -511,11 +521,6 @@ export const ERC1155M_ABIS = { name: 'price', type: 'uint80[]', }, - { - internalType: 'uint80[]', - name: 'mintFee', - type: 'uint80[]', - }, { internalType: 'uint32[]', name: 'walletLimit', diff --git a/cli-typescript/src/cmds/createCommand.ts b/cli-typescript/src/cmds/createCommand.ts index b3eddc33..4fc253e2 100644 --- a/cli-typescript/src/cmds/createCommand.ts +++ b/cli-typescript/src/cmds/createCommand.ts @@ -27,6 +27,7 @@ import { setGlobalWalletLimitCmd, setMaxMintableSupplyCmd, setMintableCmd, + setMintFeeCmd, setStagesCmd, setTimestampExpiryCmd, setTokenURISuffixCmd, @@ -203,6 +204,7 @@ export const createEvmCommand = ({ newCmd.addCommand(initContractCmd()); newCmd.addCommand(setUriCmd()); newCmd.addCommand(setStagesCmd()); + newCmd.addCommand(setMintFeeCmd()); newCmd.addCommand(setGlobalWalletLimitCmd()); newCmd.addCommand(setMaxMintableSupplyCmd()); newCmd.addCommand(setCosginerCmd()); diff --git a/cli-typescript/src/cmds/general.ts b/cli-typescript/src/cmds/general.ts index bc6454c6..80fe73e1 100644 --- a/cli-typescript/src/cmds/general.ts +++ b/cli-typescript/src/cmds/general.ts @@ -16,6 +16,7 @@ import { getTokenIdOption, getTokenUriSuffixOption, getUriOption, + mintFeeOption, } from '../utils/cmdOptions'; import newWalletAction from '../utils/cmdActions/newWalletAction'; import setUriAction from '../utils/cmdActions/setUriAction'; @@ -36,6 +37,7 @@ import { ownerMintAction } from '../utils/cmdActions/ownerMintAction'; import { checkSignerBalanceAction } from '../utils/cmdActions/checkSignerBalanceAction'; import getWalletInfoAction from '../utils/cmdActions/getWalletInfoAction'; import getProjectConfigAction from '../utils/cmdActions/getProjectConfigAction'; +import setMintFeeAction from '../utils/cmdActions/setMintFeeAction'; export const createNewWalletCmd = () => new Command('create-wallet') @@ -196,3 +198,11 @@ export const checkSignerBalanceCmd = () => .alias('csb') .description('Check the balance of the signer account for the collection.') .action(checkSignerBalanceAction); + +export const setMintFeeCmd = () => + new Command('set-mint-fee') + .command('set-mint-fee ') + .alias('smf') + .description('set the mint fee for the collection') + .addOption(mintFeeOption().makeOptionMandatory()) + .action(setMintFeeAction); diff --git a/cli-typescript/src/utils/ContractManager.ts b/cli-typescript/src/utils/ContractManager.ts index 84046f24..a14447e5 100644 --- a/cli-typescript/src/utils/ContractManager.ts +++ b/cli-typescript/src/utils/ContractManager.ts @@ -30,6 +30,7 @@ import { MagicDropCloneFactoryAbis, MagicDropTokenImplRegistryAbis, NEW_CONTRACT_INITIALIZED_EVENT_ABI, + SET_MINT_FEE_ABI, SET_TRANSFER_VALIDATOR_ABI, SUPPORTS_INTERFACE_ABI, } from '../abis'; @@ -99,6 +100,67 @@ export class ContractManager { } } + public async getMintFee( + registryAddress: Hex, + standardId: number, + implId: number, + ): Promise { + try { + const data = encodeFunctionData({ + abi: [MagicDropTokenImplRegistryAbis.getMintFee], + functionName: MagicDropTokenImplRegistryAbis.getMintFee.name, + args: [standardId, implId], + }); + + const result = await this.client.call({ + to: registryAddress, + data, + }); + + showText('Fetching mint fee...', '', false, false); + + if (!result.data) return BigInt(0); + + const decodedResult = decodeFunctionResult({ + abi: [MagicDropTokenImplRegistryAbis.getMintFee], + functionName: MagicDropTokenImplRegistryAbis.getMintFee.name, + data: result.data, + }); + + return decodedResult; + } catch (error: any) { + console.error('Error fetching deployment fee:', error.message); + throw new Error('Failed to fetch deployment fee.'); + } + } + + public async setMintFee( + contractAddress: Hex, + mintFee: bigint, + ): Promise { + try { + const data = encodeFunctionData({ + abi: [SET_MINT_FEE_ABI], + functionName: SET_MINT_FEE_ABI.name, + args: [mintFee], + }); + + showText('Setting mint fee... this will take a moment', '', false, false); + + const txHash = await this.sendTransaction({ + to: contractAddress, + data, + }); + + const receipt = await this.waitForTransactionReceipt(txHash); + + return receipt; + } catch (error: any) { + console.error('Error setting mint fee:', error.message); + throw new Error('Failed to set mint fee.'); + } + } + /** * Sends a transaction using METurnkeyServiceClient for signing. */ diff --git a/cli-typescript/src/utils/cmdActions/setMintFeeAction.ts b/cli-typescript/src/utils/cmdActions/setMintFeeAction.ts new file mode 100644 index 00000000..114bd191 --- /dev/null +++ b/cli-typescript/src/utils/cmdActions/setMintFeeAction.ts @@ -0,0 +1,36 @@ +import { Hex } from 'viem'; +import { ContractManager } from '../ContractManager'; +import { parseMintFee, setMintFee } from '../deployContract'; +import { init } from '../evmUtils'; +import { getProjectSigner } from '../turnkey'; +import { showError } from '../display'; +import { verifyContractDeployment } from '../common'; + +const setMintFeeAction = async ( + symbol: string, + params: { mintFee: number }, +) => { + try { + symbol = symbol.toLowerCase(); + + const { store } = init(symbol); + const config = store.data!; + + verifyContractDeployment(config.deployment?.contract_address); + + const { signer } = await getProjectSigner(symbol); + + const cm = new ContractManager(config.chainId, signer, symbol); + + await setMintFee({ + cm, + contractAddress: config.deployment!.contract_address as Hex, + mintFee: parseMintFee(params.mintFee.toString()), + }); + } catch (error: any) { + showError({ text: `Error initializing contract: ${error.message}` }); + process.exit(1); + } +}; + +export default setMintFeeAction; diff --git a/cli-typescript/src/utils/cmdActions/setStagesAction.ts b/cli-typescript/src/utils/cmdActions/setStagesAction.ts index d25eaaae..55e5c2e8 100644 --- a/cli-typescript/src/utils/cmdActions/setStagesAction.ts +++ b/cli-typescript/src/utils/cmdActions/setStagesAction.ts @@ -63,15 +63,13 @@ const sendERC721StagesTransaction = async ( const args = stagesData.map((stage) => { return { price: stage[0], - mintFee: stage[1], - walletLimit: stage[2], - merkleRoot: stage[3], - maxStageSupply: stage[4], - startTimeUnixSeconds: stage[5], - endTimeUnixSeconds: stage[6], + walletLimit: stage[1], + merkleRoot: stage[2], + maxStageSupply: stage[3], + startTimeUnixSeconds: stage[4], + endTimeUnixSeconds: stage[5], } as { price: bigint; - mintFee: bigint; walletLimit: number; merkleRoot: Hex; maxStageSupply: number; @@ -106,15 +104,13 @@ const sendERC1155SetupTransaction = async ( const args = stagesData.map((stage) => { return { price: stage[0], - mintFee: stage[1], - walletLimit: stage[2], - merkleRoot: stage[3], - maxStageSupply: stage[4], - startTimeUnixSeconds: stage[5], - endTimeUnixSeconds: stage[6], + walletLimit: stage[1], + merkleRoot: stage[2], + maxStageSupply: stage[3], + startTimeUnixSeconds: stage[4], + endTimeUnixSeconds: stage[5], } as { price: bigint[]; - mintFee: bigint[]; walletLimit: number[]; merkleRoot: `0x${string}`[]; maxStageSupply: number[]; diff --git a/cli-typescript/src/utils/cmdOptions.ts b/cli-typescript/src/utils/cmdOptions.ts index 28339278..bfb21b5c 100644 --- a/cli-typescript/src/utils/cmdOptions.ts +++ b/cli-typescript/src/utils/cmdOptions.ts @@ -159,3 +159,11 @@ export const getConfigFileOption = () => Path to the project configuration file. This file contains the config for the collection. `, ); + +export const mintFeeOption = () => + new Option( + '--mintFee ', + ` + The mint fee for the collection in ether. This value is used to set the mint fee for the collection. + `, + ); diff --git a/cli-typescript/src/utils/constants.ts b/cli-typescript/src/utils/constants.ts index ed18eabd..bc23e658 100644 --- a/cli-typescript/src/utils/constants.ts +++ b/cli-typescript/src/utils/constants.ts @@ -34,14 +34,14 @@ export const LIMITBREAK_TRANSFER_VALIDATOR_V3_BERACHAIN = '0x721c002b0059009a671d00ad1700c9748146cd1b'; export const ABSTRACT_FACTORY_ADDRESS = - '0x4a08d3F6881c4843232EFdE05baCfb5eAaB35d19'; + '0x01c1C2f5271aDeA338dAfba77121Fc20B5176620'; export const DEFAULT_FACTORY_ADDRESS = - '0x000000009e44eBa131196847C685F20Cd4b68aC4'; + '0x00000000bEa935F8315156894Aa4a45D3c7a0075'; export const ABSTRACT_REGISTRY_ADDRESS = - '0x9b60ad31F145ec7EE3c559153bB57928B65C0F87'; + '0x17c9921D99c1Fa6d3dC992719DA1123dCb2CaedA'; export const DEFAULT_REGISTRY_ADDRESS = - '0x00000000caF1E3978e291c5Fb53FeedB957eC146'; + '0x000000000e447e71b2EC36CD62048Dd2a1Cd0a57'; export const ICREATOR_TOKEN_INTERFACE_ID = '0xad0d7f6c'; // type(ICreatorToken).interfaceId export const TRUE_HEX = diff --git a/cli-typescript/src/utils/deployContract.ts b/cli-typescript/src/utils/deployContract.ts index 14ef025f..c84e4d29 100644 --- a/cli-typescript/src/utils/deployContract.ts +++ b/cli-typescript/src/utils/deployContract.ts @@ -22,7 +22,7 @@ import { promptForConfirmation, } from './getters'; import { ContractManager } from './ContractManager'; -import { Hex } from 'viem'; +import { Hex, parseEther } from 'viem'; import { DEFAULT_MINT_CURRENCY, SUPPORTED_CHAINS, @@ -77,6 +77,11 @@ export const deployContract = async ({ Number(standardId), Number(implId), ); + const mintFee = await cm.getMintFee( + registryAddress, + Number(standardId), + Number(implId), + ); await confirmDeployment({ name: collectionName, @@ -86,6 +91,7 @@ export const deployContract = async ({ implId: implId.toString(), chainId: cm.chainId, deploymentFee: deploymentFee.toString(), + mintFee: mintFee.toString(), }); showText('Deploying contract... this may take a minute.', '', false, false); @@ -168,6 +174,18 @@ export const deployContract = async ({ totalTokens, }); } + + const shouldSetMintFee = await promptForConfirmation( + 'Would you like to set the mint fee?', + ); + + if (shouldSetMintFee) { + await setMintFee({ + cm, + contractAddress, + mintFee, + }); + } }; /** @@ -387,13 +405,12 @@ export const getERC721ParsedStagesData = (stagesData: ERC721StageData[]) => { const parsedStagesData = stagesData.map((stage) => { return [ BigInt(stage.price), - BigInt(stage.mintFee), stage.walletLimit, stage.merkleRoot as Hex, stage.maxStageSupply, BigInt(stage.startTime), BigInt(stage.endTime), - ] as readonly [bigint, bigint, number, Hex, number, bigint, bigint]; + ] as readonly [bigint, number, Hex, number, bigint, bigint]; }); return parsedStagesData; @@ -403,21 +420,12 @@ export const getERC1155ParsedStagesData = (stagesData: ERC1155StageData[]) => { const parsedStagesData = stagesData.map((stage) => { return [ stage.price.map((price) => BigInt(price)), - stage.mintFee.map((fee) => BigInt(fee)), stage.walletLimit, stage.merkleRoot, stage.maxStageSupply, BigInt(stage.startTime), BigInt(stage.endTime), - ] as readonly [ - bigint[], - bigint[], - number[], - Hex[], - number[], - bigint, - bigint, - ]; + ] as readonly [bigint[], number[], Hex[], number[], bigint, bigint]; }); return parsedStagesData; @@ -450,7 +458,7 @@ const sendERC721SetupTransaction = async ({ }) => { try { const setupSignature = - 'function setup(string,string,uint256,uint256,address,address,(uint80,uint80,uint32,bytes32,uint24,uint256,uint256)[],address,uint96)'; + 'function setup(string,string,uint256,uint256,address,address,(uint80,uint32,bytes32,uint24,uint256,uint256)[],address,uint96)'; const abi = AbiFunction.from(setupSignature); @@ -506,7 +514,7 @@ const sendERC1155SetupTransaction = async ({ }) => { try { const setupSignature = - 'function setup(string,uint256[],uint256[],address,address,(uint80[],uint80[],uint32[],bytes32[],uint24[],uint256,uint256)[],address,uint96)'; + 'function setup(string,uint256[],uint256[],address,address,(uint80[],uint32[],bytes32[],uint24[],uint256,uint256)[],address,uint96)'; const abi = AbiFunction.from(setupSignature); @@ -535,3 +543,49 @@ const sendERC1155SetupTransaction = async ({ throw error; } }; + +export const setMintFee = async ({ + cm, + contractAddress, + mintFee, +}: { + cm: ContractManager; + contractAddress: Hex; + mintFee: bigint; +}) => { + showText( + `You are about to set the mint fee of ${collapseAddress(contractAddress)} to ${mintFee}`, + ); + + await cm.printSignerWithBalance(); + + const proceed = await promptForConfirmation('Do you want to proceed?'); + + if (!proceed) { + showText('Set mint fee cancelled'); + return; + } + + const { transactionHash } = await cm.setMintFee( + contractAddress, + parseMintFee(mintFee.toString()), + ); + + printTransactionHash(transactionHash, cm.chainId); + console.log(`Mint fee set to: ${mintFee}`); +}; + +export const parseMintFee = (mintFee: string) => { + if (!mintFee) { + console.error('No mint fee provided'); + throw new Error('No mint fee provided'); + } + + try { + const parsedFee = parseEther(mintFee); + return parsedFee; + } catch (error: any) { + console.error('Failed to parse mint fee:', error.message); + throw new Error('Failed to parse mint fee'); + } +}; diff --git a/cli-typescript/src/utils/display.ts b/cli-typescript/src/utils/display.ts index d5ff3f2e..4b232e5d 100644 --- a/cli-typescript/src/utils/display.ts +++ b/cli-typescript/src/utils/display.ts @@ -34,6 +34,7 @@ export const confirmDeployment = async (details: { implId: string; chainId: SUPPORTED_CHAINS; deploymentFee: string; + mintFee: string; }): Promise => { const { name, @@ -43,6 +44,7 @@ export const confirmDeployment = async (details: { implId, chainId, deploymentFee, + mintFee, } = details; console.log(''); @@ -56,6 +58,7 @@ export const confirmDeployment = async (details: { ); console.log(`Chain ID: ${chalk.cyan(chainId)}`); console.log(`Deployment Fee: ${chalk.cyan(deploymentFee)}`); + console.log(`Mint Fee: ${chalk.cyan(mintFee)}`); console.log('============================================================'); console.log(''); diff --git a/cli-typescript/src/utils/getters.ts b/cli-typescript/src/utils/getters.ts index d1592b32..40895236 100644 --- a/cli-typescript/src/utils/getters.ts +++ b/cli-typescript/src/utils/getters.ts @@ -255,22 +255,11 @@ export const getImplId = ( tokenStandard: TOKEN_STANDARD, useERC721C?: boolean, ): number => { - if (tokenStandard !== TOKEN_STANDARD.ERC721 || !useERC721C) { - return DEFAULT_IMPL_ID; + if (tokenStandard === TOKEN_STANDARD.ERC721 && useERC721C) { + return 2; } - switch (chainId) { - case SUPPORTED_CHAINS.ABSTRACT: - return 3; // ERC721C implementation ID / abstract - case SUPPORTED_CHAINS.BASE: - return 8; - case SUPPORTED_CHAINS.ETHEREUM: - return 7; - case SUPPORTED_CHAINS.BERACHAIN: - return 2; - default: - return 5; - } + return DEFAULT_IMPL_ID; }; export const getStandardId = (tokenStandard: TOKEN_STANDARD): string => {