UNPKG

sequence-cli

Version:

CLI for Sequence

1,681 lines (1,677 loc) 379 kB
#!/usr/bin/env node import { Command } from 'commander'; import { input, password, number } from '@inquirer/prompts'; import { Wallet, ethers } from 'ethers'; import { findSupportedNetwork } from '@0xsequence/network'; import shell from 'shelljs'; import chalk from 'chalk'; import { createWalletClient, http, getContract } from 'viem'; import { Session } from '@0xsequence/auth'; import { extractProjectIdFromAccessKey } from '@0xsequence/utils'; import figlet from 'figlet'; function isValidPrivateKey(privateKey) { try { new Wallet(privateKey); return true; } catch (error) { return false; } } const cliConsole = { error: (message) => { console.log(chalk.red(message)); }, errorFieldInBlank: () => { cliConsole.error('You cannot leave this field in blank. Please try again.'); }, warning: (message) => { console.log(chalk.yellow(`⚠️ ${message}`)); }, info: (message) => { console.log(chalk.blue(`ℹ️ ${message}`)); }, success: (message) => { console.log(chalk.green(`✅ ${message}`)); }, loading: (message) => { console.log(chalk.gray(`⏳ ${message}...`)); }, done: (message) => { console.log(chalk.greenBright(`🎉 ${message}`)); }, lineBreak: () => { console.log('\n'); }, sectionTitle: (title) => { console.log(chalk.magenta.bold(`\n=== ${title.toUpperCase()} ===\n`)); }, }; async function promptForKeyWithLogs(prompt, logs) { if (!prompt.key) { logs.forEach(log => console.log(log)); const inputKey = await input({ message: prompt.inputMessage, }); console.log(''); return inputKey || prompt.key; } return prompt.key; } async function executePromptWithRetry(promptFn, params, logs, options = { allowEmptyInput: true }) { const promptResult = await promptFn(params, logs); if (!promptResult && !options.allowEmptyInput) { cliConsole.errorFieldInBlank(); return await executePromptWithRetry(promptFn, params, logs, options); } return promptResult; } async function promptForProjectAccessKeyWithLogs(projectAccessKey, options = { allowEmptyInput: true }) { const logsArray = [ 'Please provide the Project Access Key for your project.', 'Your access key can be found at https://sequence.build under the project settings.', ]; if (options.allowEmptyInput) { logsArray.push('To skip and use the default test access key, press enter.'); } return await executePromptWithRetry(promptForKeyWithLogs, { key: projectAccessKey, inputMessage: 'Project Access Key:' }, logsArray, options); } async function promptForWaaSConfigKeyWithLogs(waasConfigKey, options = { allowEmptyInput: true }) { const logsArray = [ 'Please provide the WaaS Config Key for your project.', 'Your config key can be found at https://sequence.build under the embedded wallet settings.', ]; if (options.allowEmptyInput) { logsArray.push('To skip and use the default test config key, press enter.'); } return await executePromptWithRetry(promptForKeyWithLogs, { key: waasConfigKey, inputMessage: 'WaaS Config Key:' }, logsArray, options); } async function promptForGoogleClientIdWithLogs(googleClientId, options = { allowEmptyInput: true }) { const logsArray = [ 'Please provide the Google Client ID for your project.', 'Your client ID can be found at https://console.cloud.google.com/apis/credentials.', ]; if (options.allowEmptyInput) { logsArray.push('To skip and use the default test client ID, press enter.'); } return await executePromptWithRetry(promptForKeyWithLogs, { key: googleClientId, inputMessage: 'Google Client ID:' }, logsArray, options); } async function promptForAppleClientIdWithLogs(appleClientId, options = { allowEmptyInput: true }) { const logsArray = [ 'Please provide the Apple Client ID for your project.', 'Your client ID can be found at https://developer.apple.com/account/resources/identifiers/list/serviceId', ]; if (options.allowEmptyInput) { logsArray.push('To skip and use the default test client ID, press enter.'); } return await executePromptWithRetry(promptForKeyWithLogs, { key: appleClientId, inputMessage: 'Apple Client ID:' }, logsArray, options); } async function promptForWalletConnectIdWithLogs(walletConnectId, options = { allowEmptyInput: true }) { const logsArray = ['Please provide the Wallet Connect ID for your project.']; if (options.allowEmptyInput) { logsArray.push('To skip and use the default test client ID, press enter.'); } return await executePromptWithRetry(promptForKeyWithLogs, { key: walletConnectId, inputMessage: 'Wallet Connect ID:' }, logsArray, options); } async function promptForWalletAppUrlWithLogs(walletAppUrl, options = { allowEmptyInput: true }) { const logsArray = [ 'Please provide the Wallet App URL for your project.', 'Default: https://acme.ecosystem-demo.xyz', ]; if (options.allowEmptyInput) { logsArray.push('To skip and use the default wallet app URL, press enter.'); } return await executePromptWithRetry(promptForKeyWithLogs, { key: walletAppUrl, inputMessage: 'Wallet App URL:' }, logsArray, options); } async function promptForJwtAccessKeyWithLogs(jwtAccessKey, options = { allowEmptyInput: true }) { const logsArray = [ 'To get your jwt access key follow the first step in https://docs.sequence.xyz/guides/metadata-guide/', ]; if (options.allowEmptyInput) { logsArray.push('To skip and use the default jwt access key, press enter.'); } return await executePromptWithRetry(promptForKeyWithLogs, { key: jwtAccessKey, inputMessage: 'JWT Access Key:' }, logsArray, options); } async function promptForTrailsApiKeyWithLogs(trailsApiKey, options = { allowEmptyInput: true }) { const logsArray = [ 'Please provide your Trails API key for your project.', 'Request an access key at https://t.me/build_with_trails', ]; if (options.allowEmptyInput) { logsArray.push('Press Enter to skip.'); } return await executePromptWithRetry(promptForKeyWithLogs, { key: trailsApiKey, inputMessage: 'Trails API key:' }, logsArray, options); } function writeToEnvFile(envKeys, options) { Object.entries(envKeys).forEach(([key, value]) => { if (value && value !== '') { shell.exec(`echo ${key}=${value} >> ${options.pathToWrite ? options.pathToWrite : '.env'}`, { silent: !options.verbose }); } }); } function writeDefaultKeysToEnvFileIfMissing(envExampleLines, envKeys, options) { const missingKeys = Object.entries(envKeys) .filter(([_, value]) => value === undefined || value === '') .map(([key, _]) => key); const envFilePath = options.pathToWrite ? options.pathToWrite : '.env'; const envFileContent = shell.cat(envFilePath).toString(); envExampleLines.forEach(line => { if (missingKeys.some(key => line.includes(key))) { if (!envFileContent.includes(line)) { shell.exec(`echo ${line} >> ${envFilePath}`, { silent: !options.verbose, }); } } }); } function writeToWranglerEnvFile(envKeys, options) { Object.entries(envKeys).forEach(([key, value]) => { if (value && value !== '') { const formattedValue = typeof value === 'string' ? `"${value}"` : value; shell.exec(`echo ${key} = ${formattedValue} >> ${options.pathToWrite ? options.pathToWrite : 'wrangler.toml'}`, { silent: !options.verbose }); } }); } function appendToWranglerConfig(section, wranglerConfigPath, verbose) { const command = `echo ${section} >> ${wranglerConfigPath}`; shell.exec(command, { silent: !verbose }); } function addVarsToWranglerConfig(wranglerConfigPath, verbose) { appendToWranglerConfig('[vars]', wranglerConfigPath, verbose); } function addDevToWranglerConfig(wranglerConfigPath, verbose) { appendToWranglerConfig('[dev]', wranglerConfigPath, verbose); } function checkIfDirectoryExists(path) { return shell.test('-d', path); } const ERC1155_ABI = [ { anonymous: false, inputs: [ { indexed: true, internalType: 'address', name: '_owner', type: 'address', }, { indexed: true, internalType: 'address', name: '_operator', type: 'address', }, { indexed: false, internalType: 'bool', name: '_approved', type: 'bool', }, ], name: 'ApprovalForAll', type: 'event', }, { anonymous: false, inputs: [ { indexed: true, internalType: 'address', name: '_operator', type: 'address', }, { indexed: true, internalType: 'address', name: '_from', type: 'address', }, { indexed: true, internalType: 'address', name: '_to', type: 'address', }, { indexed: false, internalType: 'uint256[]', name: '_ids', type: 'uint256[]', }, { indexed: false, internalType: 'uint256[]', name: '_amounts', type: 'uint256[]', }, ], name: 'TransferBatch', type: 'event', }, { anonymous: false, inputs: [ { indexed: true, internalType: 'address', name: '_operator', type: 'address', }, { indexed: true, internalType: 'address', name: '_from', type: 'address', }, { indexed: true, internalType: 'address', name: '_to', type: 'address', }, { indexed: false, internalType: 'uint256', name: '_id', type: 'uint256', }, { indexed: false, internalType: 'uint256', name: '_amount', type: 'uint256', }, ], name: 'TransferSingle', type: 'event', }, { inputs: [ { internalType: 'address', name: '_owner', type: 'address', }, { internalType: 'uint256', name: '_id', type: 'uint256', }, ], name: 'balanceOf', outputs: [ { internalType: 'uint256', name: '', type: 'uint256', }, ], stateMutability: 'view', type: 'function', }, { inputs: [ { internalType: 'address[]', name: '_owners', type: 'address[]', }, { internalType: 'uint256[]', name: '_ids', type: 'uint256[]', }, ], name: 'balanceOfBatch', outputs: [ { internalType: 'uint256[]', name: '', type: 'uint256[]', }, ], stateMutability: 'view', type: 'function', }, { inputs: [ { internalType: 'uint256', name: '_id', type: 'uint256', }, ], name: 'getIDBinIndex', outputs: [ { internalType: 'uint256', name: 'bin', type: 'uint256', }, { internalType: 'uint256', name: 'index', type: 'uint256', }, ], stateMutability: 'pure', type: 'function', }, { inputs: [ { internalType: 'uint256', name: '_binValues', type: 'uint256', }, { internalType: 'uint256', name: '_index', type: 'uint256', }, ], name: 'getValueInBin', outputs: [ { internalType: 'uint256', name: '', type: 'uint256', }, ], stateMutability: 'pure', type: 'function', }, { inputs: [ { internalType: 'address', name: '_owner', type: 'address', }, { internalType: 'address', name: '_operator', type: 'address', }, ], name: 'isApprovedForAll', outputs: [ { internalType: 'bool', name: 'isOperator', type: 'bool', }, ], stateMutability: 'view', type: 'function', }, { inputs: [ { internalType: 'address', name: '_from', type: 'address', }, { internalType: 'address', name: '_to', type: 'address', }, { internalType: 'uint256[]', name: '_ids', type: 'uint256[]', }, { internalType: 'uint256[]', name: '_amounts', type: 'uint256[]', }, { internalType: 'bytes', name: '_data', type: 'bytes', }, ], name: 'safeBatchTransferFrom', outputs: [], stateMutability: 'nonpayable', type: 'function', }, { inputs: [ { internalType: 'address', name: '_from', type: 'address', }, { internalType: 'address', name: '_to', type: 'address', }, { internalType: 'uint256', name: '_id', type: 'uint256', }, { internalType: 'uint256', name: '_amount', type: 'uint256', }, { internalType: 'bytes', name: '_data', type: 'bytes', }, ], name: 'safeTransferFrom', outputs: [], stateMutability: 'nonpayable', type: 'function', }, { inputs: [ { internalType: 'address', name: '_operator', type: 'address', }, { internalType: 'bool', name: '_approved', type: 'bool', }, ], name: 'setApprovalForAll', outputs: [], stateMutability: 'nonpayable', type: 'function', }, { inputs: [ { internalType: 'bytes4', name: '_interfaceID', type: 'bytes4', }, ], name: 'supportsInterface', outputs: [ { internalType: 'bool', name: '', type: 'bool', }, ], stateMutability: 'pure', type: 'function', }, ]; const SequenceMarketplace_V1_ABI = [ { inputs: [{ internalType: 'address', name: '_owner', type: 'address' }], stateMutability: 'nonpayable', type: 'constructor', }, { inputs: [], name: 'InvalidAdditionalFees', type: 'error' }, { inputs: [], name: 'InvalidBatchRequest', type: 'error' }, { inputs: [], name: 'InvalidCurrency', type: 'error' }, { inputs: [ { internalType: 'address', name: 'currency', type: 'address' }, { internalType: 'uint256', name: 'quantity', type: 'uint256' }, { internalType: 'address', name: 'owner', type: 'address' }, ], name: 'InvalidCurrencyApproval', type: 'error', }, { inputs: [], name: 'InvalidExpiry', type: 'error' }, { inputs: [], name: 'InvalidPrice', type: 'error' }, { inputs: [], name: 'InvalidQuantity', type: 'error' }, { inputs: [{ internalType: 'uint256', name: 'requestId', type: 'uint256' }], name: 'InvalidRequestId', type: 'error', }, { inputs: [], name: 'InvalidRoyalty', type: 'error' }, { inputs: [ { internalType: 'address', name: 'tokenContract', type: 'address' }, { internalType: 'uint256', name: 'tokenId', type: 'uint256' }, { internalType: 'uint256', name: 'quantity', type: 'uint256' }, { internalType: 'address', name: 'owner', type: 'address' }, ], name: 'InvalidTokenApproval', type: 'error', }, { inputs: [ { internalType: 'address', name: 'contractAddress', type: 'address' }, { internalType: 'bytes4', name: 'interfaceId', type: 'bytes4' }, ], name: 'UnsupportedContractInterface', type: 'error', }, { anonymous: false, inputs: [ { indexed: true, internalType: 'address', name: 'tokenContract', type: 'address', }, { indexed: false, internalType: 'address', name: 'recipient', type: 'address', }, { indexed: false, internalType: 'uint96', name: 'fee', type: 'uint96' }, ], name: 'CustomRoyaltyChanged', type: 'event', }, { anonymous: false, inputs: [ { indexed: true, internalType: 'address', name: 'previousOwner', type: 'address', }, { indexed: true, internalType: 'address', name: 'newOwner', type: 'address', }, ], name: 'OwnershipTransferred', type: 'event', }, { anonymous: false, inputs: [ { indexed: true, internalType: 'uint256', name: 'requestId', type: 'uint256', }, { indexed: true, internalType: 'address', name: 'buyer', type: 'address', }, { indexed: true, internalType: 'address', name: 'tokenContract', type: 'address', }, { indexed: false, internalType: 'address', name: 'receiver', type: 'address', }, { indexed: false, internalType: 'uint256', name: 'quantity', type: 'uint256', }, { indexed: false, internalType: 'uint256', name: 'quantityRemaining', type: 'uint256', }, ], name: 'RequestAccepted', type: 'event', }, { anonymous: false, inputs: [ { indexed: true, internalType: 'uint256', name: 'requestId', type: 'uint256', }, { indexed: true, internalType: 'address', name: 'tokenContract', type: 'address', }, ], name: 'RequestCancelled', type: 'event', }, { anonymous: false, inputs: [ { indexed: true, internalType: 'uint256', name: 'requestId', type: 'uint256', }, { indexed: true, internalType: 'address', name: 'creator', type: 'address', }, { indexed: true, internalType: 'address', name: 'tokenContract', type: 'address', }, { indexed: false, internalType: 'uint256', name: 'tokenId', type: 'uint256', }, { indexed: false, internalType: 'bool', name: 'isListing', type: 'bool' }, { indexed: false, internalType: 'uint256', name: 'quantity', type: 'uint256', }, { indexed: false, internalType: 'address', name: 'currency', type: 'address', }, { indexed: false, internalType: 'uint256', name: 'pricePerToken', type: 'uint256', }, { indexed: false, internalType: 'uint256', name: 'expiry', type: 'uint256', }, ], name: 'RequestCreated', type: 'event', }, { inputs: [ { internalType: 'uint256', name: 'requestId', type: 'uint256' }, { internalType: 'uint256', name: 'quantity', type: 'uint256' }, { internalType: 'address', name: 'receiver', type: 'address' }, { internalType: 'uint256[]', name: 'additionalFees', type: 'uint256[]' }, { internalType: 'address[]', name: 'additionalFeeReceivers', type: 'address[]', }, ], name: 'acceptRequest', outputs: [], stateMutability: 'nonpayable', type: 'function', }, { inputs: [ { internalType: 'uint256[]', name: 'requestIds', type: 'uint256[]' }, { internalType: 'uint256[]', name: 'quantities', type: 'uint256[]' }, { internalType: 'address[]', name: 'receivers', type: 'address[]' }, { internalType: 'uint256[]', name: 'additionalFees', type: 'uint256[]' }, { internalType: 'address[]', name: 'additionalFeeReceivers', type: 'address[]', }, ], name: 'acceptRequestBatch', outputs: [], stateMutability: 'nonpayable', type: 'function', }, { inputs: [{ internalType: 'uint256', name: 'requestId', type: 'uint256' }], name: 'cancelRequest', outputs: [], stateMutability: 'nonpayable', type: 'function', }, { inputs: [ { internalType: 'uint256[]', name: 'requestIds', type: 'uint256[]' }, ], name: 'cancelRequestBatch', outputs: [], stateMutability: 'nonpayable', type: 'function', }, { inputs: [ { components: [ { internalType: 'bool', name: 'isListing', type: 'bool' }, { internalType: 'bool', name: 'isERC1155', type: 'bool' }, { internalType: 'address', name: 'tokenContract', type: 'address' }, { internalType: 'uint256', name: 'tokenId', type: 'uint256' }, { internalType: 'uint256', name: 'quantity', type: 'uint256' }, { internalType: 'uint96', name: 'expiry', type: 'uint96' }, { internalType: 'address', name: 'currency', type: 'address' }, { internalType: 'uint256', name: 'pricePerToken', type: 'uint256' }, ], internalType: 'struct ISequenceMarketStorage.RequestParams', name: 'request', type: 'tuple', }, ], name: 'createRequest', outputs: [{ internalType: 'uint256', name: 'requestId', type: 'uint256' }], stateMutability: 'nonpayable', type: 'function', }, { inputs: [ { components: [ { internalType: 'bool', name: 'isListing', type: 'bool' }, { internalType: 'bool', name: 'isERC1155', type: 'bool' }, { internalType: 'address', name: 'tokenContract', type: 'address' }, { internalType: 'uint256', name: 'tokenId', type: 'uint256' }, { internalType: 'uint256', name: 'quantity', type: 'uint256' }, { internalType: 'uint96', name: 'expiry', type: 'uint96' }, { internalType: 'address', name: 'currency', type: 'address' }, { internalType: 'uint256', name: 'pricePerToken', type: 'uint256' }, ], internalType: 'struct ISequenceMarketStorage.RequestParams[]', name: 'requests', type: 'tuple[]', }, ], name: 'createRequestBatch', outputs: [ { internalType: 'uint256[]', name: 'requestIds', type: 'uint256[]' }, ], stateMutability: 'nonpayable', type: 'function', }, { inputs: [{ internalType: 'address', name: '', type: 'address' }], name: 'customRoyalties', outputs: [ { internalType: 'address', name: 'recipient', type: 'address' }, { internalType: 'uint96', name: 'fee', type: 'uint96' }, ], stateMutability: 'view', type: 'function', }, { inputs: [{ internalType: 'uint256', name: 'requestId', type: 'uint256' }], name: 'getRequest', outputs: [ { components: [ { internalType: 'address', name: 'creator', type: 'address' }, { internalType: 'bool', name: 'isListing', type: 'bool' }, { internalType: 'bool', name: 'isERC1155', type: 'bool' }, { internalType: 'address', name: 'tokenContract', type: 'address' }, { internalType: 'uint256', name: 'tokenId', type: 'uint256' }, { internalType: 'uint256', name: 'quantity', type: 'uint256' }, { internalType: 'uint96', name: 'expiry', type: 'uint96' }, { internalType: 'address', name: 'currency', type: 'address' }, { internalType: 'uint256', name: 'pricePerToken', type: 'uint256' }, ], internalType: 'struct ISequenceMarketStorage.Request', name: 'request', type: 'tuple', }, ], stateMutability: 'view', type: 'function', }, { inputs: [ { internalType: 'uint256[]', name: 'requestIds', type: 'uint256[]' }, ], name: 'getRequestBatch', outputs: [ { components: [ { internalType: 'address', name: 'creator', type: 'address' }, { internalType: 'bool', name: 'isListing', type: 'bool' }, { internalType: 'bool', name: 'isERC1155', type: 'bool' }, { internalType: 'address', name: 'tokenContract', type: 'address' }, { internalType: 'uint256', name: 'tokenId', type: 'uint256' }, { internalType: 'uint256', name: 'quantity', type: 'uint256' }, { internalType: 'uint96', name: 'expiry', type: 'uint96' }, { internalType: 'address', name: 'currency', type: 'address' }, { internalType: 'uint256', name: 'pricePerToken', type: 'uint256' }, ], internalType: 'struct ISequenceMarketStorage.Request[]', name: 'requests', type: 'tuple[]', }, ], stateMutability: 'view', type: 'function', }, { inputs: [ { internalType: 'address', name: 'tokenContract', type: 'address' }, { internalType: 'uint256', name: 'tokenId', type: 'uint256' }, { internalType: 'uint256', name: 'cost', type: 'uint256' }, ], name: 'getRoyaltyInfo', outputs: [ { internalType: 'address', name: 'recipient', type: 'address' }, { internalType: 'uint256', name: 'royalty', type: 'uint256' }, ], stateMutability: 'view', type: 'function', }, { inputs: [ { internalType: 'uint256', name: 'requestId', type: 'uint256' }, { internalType: 'uint256', name: 'quantity', type: 'uint256' }, ], name: 'isRequestValid', outputs: [ { internalType: 'bool', name: 'valid', type: 'bool' }, { components: [ { internalType: 'address', name: 'creator', type: 'address' }, { internalType: 'bool', name: 'isListing', type: 'bool' }, { internalType: 'bool', name: 'isERC1155', type: 'bool' }, { internalType: 'address', name: 'tokenContract', type: 'address' }, { internalType: 'uint256', name: 'tokenId', type: 'uint256' }, { internalType: 'uint256', name: 'quantity', type: 'uint256' }, { internalType: 'uint96', name: 'expiry', type: 'uint96' }, { internalType: 'address', name: 'currency', type: 'address' }, { internalType: 'uint256', name: 'pricePerToken', type: 'uint256' }, ], internalType: 'struct ISequenceMarketStorage.Request', name: 'request', type: 'tuple', }, ], stateMutability: 'view', type: 'function', }, { inputs: [ { internalType: 'uint256[]', name: 'requestIds', type: 'uint256[]' }, { internalType: 'uint256[]', name: 'quantities', type: 'uint256[]' }, ], name: 'isRequestValidBatch', outputs: [ { internalType: 'bool[]', name: 'valid', type: 'bool[]' }, { components: [ { internalType: 'address', name: 'creator', type: 'address' }, { internalType: 'bool', name: 'isListing', type: 'bool' }, { internalType: 'bool', name: 'isERC1155', type: 'bool' }, { internalType: 'address', name: 'tokenContract', type: 'address' }, { internalType: 'uint256', name: 'tokenId', type: 'uint256' }, { internalType: 'uint256', name: 'quantity', type: 'uint256' }, { internalType: 'uint96', name: 'expiry', type: 'uint96' }, { internalType: 'address', name: 'currency', type: 'address' }, { internalType: 'uint256', name: 'pricePerToken', type: 'uint256' }, ], internalType: 'struct ISequenceMarketStorage.Request[]', name: 'requests', type: 'tuple[]', }, ], stateMutability: 'view', type: 'function', }, { inputs: [], name: 'owner', outputs: [{ internalType: 'address', name: '', type: 'address' }], stateMutability: 'view', type: 'function', }, { inputs: [], name: 'renounceOwnership', outputs: [], stateMutability: 'nonpayable', type: 'function', }, { inputs: [ { internalType: 'address', name: 'tokenContract', type: 'address' }, { internalType: 'address', name: 'recipient', type: 'address' }, { internalType: 'uint96', name: 'fee', type: 'uint96' }, ], name: 'setRoyaltyInfo', outputs: [], stateMutability: 'nonpayable', type: 'function', }, { inputs: [{ internalType: 'address', name: 'newOwner', type: 'address' }], name: 'transferOwnership', outputs: [], stateMutability: 'nonpayable', type: 'function', }, ]; const ERC721_ABI = [ { type: 'constructor', inputs: [], stateMutability: 'nonpayable', }, { type: 'function', name: 'DEFAULT_ADMIN_ROLE', inputs: [], outputs: [ { name: '', type: 'bytes32', internalType: 'bytes32', }, ], stateMutability: 'view', }, { type: 'function', name: 'approve', inputs: [ { name: 'to', type: 'address', internalType: 'address', }, { name: 'tokenId', type: 'uint256', internalType: 'uint256', }, ], outputs: [], stateMutability: 'payable', }, { type: 'function', name: 'balanceOf', inputs: [ { name: 'owner', type: 'address', internalType: 'address', }, ], outputs: [ { name: '', type: 'uint256', internalType: 'uint256', }, ], stateMutability: 'view', }, { type: 'function', name: 'batchBurn', inputs: [ { name: 'tokenIds', type: 'uint256[]', internalType: 'uint256[]', }, ], outputs: [], stateMutability: 'nonpayable', }, { type: 'function', name: 'burn', inputs: [ { name: 'tokenId', type: 'uint256', internalType: 'uint256', }, ], outputs: [], stateMutability: 'nonpayable', }, { type: 'function', name: 'contractURI', inputs: [], outputs: [ { name: '', type: 'string', internalType: 'string', }, ], stateMutability: 'view', }, { type: 'function', name: 'explicitOwnershipOf', inputs: [ { name: 'tokenId', type: 'uint256', internalType: 'uint256', }, ], outputs: [ { name: '', type: 'tuple', internalType: 'struct IERC721A.TokenOwnership', components: [ { name: 'addr', type: 'address', internalType: 'address', }, { name: 'startTimestamp', type: 'uint64', internalType: 'uint64', }, { name: 'burned', type: 'bool', internalType: 'bool', }, { name: 'extraData', type: 'uint24', internalType: 'uint24', }, ], }, ], stateMutability: 'view', }, { type: 'function', name: 'explicitOwnershipsOf', inputs: [ { name: 'tokenIds', type: 'uint256[]', internalType: 'uint256[]', }, ], outputs: [ { name: '', type: 'tuple[]', internalType: 'struct IERC721A.TokenOwnership[]', components: [ { name: 'addr', type: 'address', internalType: 'address', }, { name: 'startTimestamp', type: 'uint64', internalType: 'uint64', }, { name: 'burned', type: 'bool', internalType: 'bool', }, { name: 'extraData', type: 'uint24', internalType: 'uint24', }, ], }, ], stateMutability: 'view', }, { type: 'function', name: 'getApproved', inputs: [ { name: 'tokenId', type: 'uint256', internalType: 'uint256', }, ], outputs: [ { name: '', type: 'address', internalType: 'address', }, ], stateMutability: 'view', }, { type: 'function', name: 'getRoleAdmin', inputs: [ { name: 'role', type: 'bytes32', internalType: 'bytes32', }, ], outputs: [ { name: '', type: 'bytes32', internalType: 'bytes32', }, ], stateMutability: 'view', }, { type: 'function', name: 'getRoleMember', inputs: [ { name: 'role', type: 'bytes32', internalType: 'bytes32', }, { name: 'index', type: 'uint256', internalType: 'uint256', }, ], outputs: [ { name: '', type: 'address', internalType: 'address', }, ], stateMutability: 'view', }, { type: 'function', name: 'getRoleMemberCount', inputs: [ { name: 'role', type: 'bytes32', internalType: 'bytes32', }, ], outputs: [ { name: '', type: 'uint256', internalType: 'uint256', }, ], stateMutability: 'view', }, { type: 'function', name: 'grantRole', inputs: [ { name: 'role', type: 'bytes32', internalType: 'bytes32', }, { name: 'account', type: 'address', internalType: 'address', }, ], outputs: [], stateMutability: 'nonpayable', }, { type: 'function', name: 'hasRole', inputs: [ { name: 'role', type: 'bytes32', internalType: 'bytes32', }, { name: 'account', type: 'address', internalType: 'address', }, ], outputs: [ { name: '', type: 'bool', internalType: 'bool', }, ], stateMutability: 'view', }, { type: 'function', name: 'initialize', inputs: [ { name: 'owner', type: 'address', internalType: 'address', }, { name: 'tokenName', type: 'string', internalType: 'string', }, { name: 'tokenSymbol', type: 'string', internalType: 'string', }, { name: 'tokenBaseURI', type: 'string', internalType: 'string', }, { name: 'tokenContractURI', type: 'string', internalType: 'string', }, { name: 'royaltyReceiver', type: 'address', internalType: 'address', }, { name: 'royaltyFeeNumerator', type: 'uint96', internalType: 'uint96', }, ], outputs: [], stateMutability: 'nonpayable', }, { type: 'function', name: 'isApprovedForAll', inputs: [ { name: 'owner', type: 'address', internalType: 'address', }, { name: 'operator', type: 'address', internalType: 'address', }, ], outputs: [ { name: '', type: 'bool', internalType: 'bool', }, ], stateMutability: 'view', }, { type: 'function', name: 'mint', inputs: [ { name: 'to', type: 'address', internalType: 'address', }, { name: 'amount', type: 'uint256', internalType: 'uint256', }, ], outputs: [], stateMutability: 'nonpayable', }, { type: 'function', name: 'name', inputs: [], outputs: [ { name: '', type: 'string', internalType: 'string', }, ], stateMutability: 'view', }, { type: 'function', name: 'ownerOf', inputs: [ { name: 'tokenId', type: 'uint256', internalType: 'uint256', }, ], outputs: [ { name: '', type: 'address', internalType: 'address', }, ], stateMutability: 'view', }, { type: 'function', name: 'renounceRole', inputs: [ { name: 'role', type: 'bytes32', internalType: 'bytes32', }, { name: 'account', type: 'address', internalType: 'address', }, ], outputs: [], stateMutability: 'nonpayable', }, { type: 'function', name: 'revokeRole', inputs: [ { name: 'role', type: 'bytes32', internalType: 'bytes32', }, { name: 'account', type: 'address', internalType: 'address', }, ], outputs: [], stateMutability: 'nonpayable', }, { type: 'function', name: 'royaltyInfo', inputs: [ { name: 'tokenId', type: 'uint256', internalType: 'uint256', }, { name: 'salePrice', type: 'uint256', internalType: 'uint256', }, ], outputs: [ { name: '', type: 'address', internalType: 'address', }, { name: '', type: 'uint256', internalType: 'uint256', }, ], stateMutability: 'view', }, { type: 'function', name: 'safeTransferFrom', inputs: [ { name: 'from', type: 'address', internalType: 'address', }, { name: 'to', type: 'address', internalType: 'address', }, { name: 'tokenId', type: 'uint256', internalType: 'uint256', }, ], outputs: [], stateMutability: 'payable', }, { type: 'function', name: 'safeTransferFrom', inputs: [ { name: 'from', type: 'address', internalType: 'address', }, { name: 'to', type: 'address', internalType: 'address', }, { name: 'tokenId', type: 'uint256', internalType: 'uint256', }, { name: '_data', type: 'bytes', internalType: 'bytes', }, ], outputs: [], stateMutability: 'payable', }, { type: 'function', name: 'setApprovalForAll', inputs: [ { name: 'operator', type: 'address', internalType: 'address', }, { name: 'approved', type: 'bool', internalType: 'bool', }, ], outputs: [], stateMutability: 'nonpayable', }, { type: 'function', name: 'setBaseMetadataURI', inputs: [ { name: 'tokenBaseURI', type: 'string', internalType: 'string', }, ], outputs: [], stateMutability: 'nonpayable', }, { type: 'function', name: 'setContractURI', inputs: [ { name: 'tokenContractURI', type: 'string', internalType: 'string', }, ], outputs: [], stateMutability: 'nonpayable', }, { type: 'function', name: 'setDefaultRoyalty', inputs: [ { name: 'receiver', type: 'address', internalType: 'address', }, { name: 'feeNumerator', type: 'uint96', internalType: 'uint96', }, ], outputs: [], stateMutability: 'nonpayable', }, { type: 'function', name: 'setNameAndSymbol', inputs: [ { name: 'tokenName', type: 'string', internalType: 'string', }, { name: 'tokenSymbol', type: 'string', internalType: 'string', }, ], outputs: [], stateMutability: 'nonpayable', }, { type: 'function', name: 'setTokenRoyalty', inputs: [ { name: 'tokenId', type: 'uint256', internalType: 'uint256', }, { name: 'receiver', type: 'address', internalType: 'address', }, { name: 'feeNumerator', type: 'uint96', internalType: 'uint96', }, ], outputs: [], stateMutability: 'nonpayable', }, { type: 'function', name: 'supportsInterface', inputs: [ { name: 'interfaceId', type: 'bytes4', internalType: 'bytes4', }, ], outputs: [ { name: '', type: 'bool', internalType: 'bool', }, ], stateMutability: 'view', }, { type: 'function', name: 'symbol', inputs: [], outputs: [ { name: '', type: 'string', internalType: 'string', }, ], stateMutability: 'view', }, { type: 'function', name: 'tokenURI', inputs: [ { name: 'tokenId', type: 'uint256', internalType: 'uint256', }, ], outputs: [ { name: '', type: 'string', internalType: 'string', }, ], stateMutability: 'view', }, { type: 'function', name: 'tokensOfOwner', inputs: [ { name: 'owner', type: 'address', internalType: 'address', }, ], outputs: [ { name: '', type: 'uint256[]', int