Skip to content

Commit

Permalink
Merge pull request #6 from neftyblocks/feature/pfp-generator
Browse files Browse the repository at this point in the history
Generate PFPs command
  • Loading branch information
jandrad authored Sep 23, 2023
2 parents 916276d + af4cd5c commit 5e89031
Show file tree
Hide file tree
Showing 28 changed files with 1,601 additions and 148 deletions.
206 changes: 162 additions & 44 deletions README.md

Large diffs are not rendered by default.

114 changes: 109 additions & 5 deletions oclif.manifest.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "0.1.2",
"version": "0.1.3",
"commands": {
"assets": {
"id": "assets",
Expand Down Expand Up @@ -163,8 +163,8 @@
"flags": {},
"args": {}
},
"generate:mint-metadata": {
"id": "generate:mint-metadata",
"generate:mint-file": {
"id": "generate:mint-file",
"description": "Generates the file to batch mint assets in a collection. Each schema will be a different sheet.",
"strict": true,
"pluginName": "@nefty/cli",
Expand Down Expand Up @@ -206,8 +206,50 @@
}
}
},
"generate:template-metadata": {
"id": "generate:template-metadata",
"generate:pfp-file": {
"id": "generate:pfp-file",
"description": "Generates the file to generate a pfp collection with the specified layers.",
"strict": true,
"pluginName": "@nefty/cli",
"pluginAlias": "@nefty/cli",
"pluginType": "core",
"aliases": [],
"examples": [
{
"command": "<%= config.bin %> <%= command.id %> pfp-layers.xlsx -l Body -l Face -l Hair",
"description": "Generates the file to create pfps with the layers Body, Face and Hair and saves it in the current directory in a file called pfp-layers.xlsx."
},
{
"command": "<%= config.bin %> <%= command.id %> pfp-layers.xlsx -l Body -l Face -l Hair -a",
"description": "Generates the file to create pfps with the layers Body, Face and Hair with advanced headers and saves it in the current directory in a file called pfp-layers.xlsx."
}
],
"flags": {
"layers": {
"name": "layers",
"type": "option",
"char": "l",
"description": "The names of the layers to include in the file.",
"multiple": true
},
"advanced": {
"name": "advanced",
"type": "boolean",
"char": "a",
"description": "Include advanced headers.",
"allowNo": false
}
},
"args": {
"output": {
"name": "output",
"description": "Location where the file will be generated.",
"required": true
}
}
},
"generate:template-file": {
"id": "generate:template-file",
"description": "Generates the file to batch create templates in a collection. Each schema will be a different sheet.",
"strict": true,
"pluginName": "@nefty/cli",
Expand Down Expand Up @@ -249,6 +291,68 @@
}
}
},
"pfps:generate": {
"id": "pfps:generate",
"description": "Generates the images and attributes for a pfp collection.",
"strict": true,
"pluginName": "@nefty/cli",
"pluginAlias": "@nefty/cli",
"pluginType": "core",
"aliases": [],
"examples": [
{
"command": "<%= config.bin %> <%= command.id %> pfps-specs.xlsx pfps",
"description": "Generates all the pfps defined in the pfps-specs.xlsx file and saves them in the pfps directory."
}
],
"flags": {
"rootDir": {
"name": "rootDir",
"type": "option",
"char": "r",
"description": "Directory where the assets are stored.",
"multiple": false
},
"resizeWidth": {
"name": "resizeWidth",
"type": "option",
"char": "w",
"description": "Width to resize the images to.",
"multiple": false
},
"quantity": {
"name": "quantity",
"type": "option",
"char": "q",
"description": "Number of pfps to generate.",
"required": true,
"multiple": false
}
},
"args": {
"input": {
"name": "input",
"description": "Location or google sheets id of the excel file with the pfps definitions.",
"required": true
},
"output": {
"name": "output",
"description": "Directory where the images will be saved.",
"required": true
}
}
},
"pfps": {
"id": "pfps",
"description": "Commands to manage a PFP collection.",
"strict": true,
"pluginName": "@nefty/cli",
"pluginAlias": "@nefty/cli",
"pluginType": "core",
"aliases": [],
"flags": {},
"args": {}
},
"templates:create": {
"id": "templates:create",
"description": "Create templates in a collection by batches using a spreadsheet.",
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@nefty/cli",
"version": "0.1.2",
"version": "0.1.3",
"description": "The NeftyBlocks cli will help you manage your collection with commands to create templates, mint assets, and more.",
"author": "NeftyBlocks",
"bin": {
Expand All @@ -25,9 +25,11 @@
"@wharfkit/wallet-plugin-anchor": "^1.0.0",
"@wharfkit/wallet-plugin-privatekey": "^1.0.0",
"atomicassets": "^1.5.1",
"cli-progress": "^3.12.0",
"node-fetch": "2.6.7",
"qrcode-terminal": "^0.12.0",
"read-excel-file": "^5.6.1",
"sharp": "^0.32.5",
"write-excel-file": "^1.4.27"
},
"devDependencies": {
Expand Down
6 changes: 5 additions & 1 deletion src/base/BaseCommand.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import { Command } from '@oclif/core';
import { CliConfig } from '../types/cli-config';
import { CliConfig } from '../types';
import { readConfiguration } from '../utils/config-utils';
import { getSession } from '../services/antelope-service';

export abstract class BaseCommand extends Command {
async catch(error: any) {
this.log(error.message);
}

async getCliConfig(requireSession = true): Promise<CliConfig> {
const config = readConfiguration(this.config.configDir);
if (!config) {
Expand Down
45 changes: 18 additions & 27 deletions src/commands/assets/mint.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,20 @@
import { ux, Flags, Args } from '@oclif/core';
import readXlsxFile, { readSheetNames } from 'read-excel-file/node';
import { MintData, mintAssets } from '../../services/asset-service';
import { mintAssets } from '../../services/asset-service';
import { Cell, Row } from 'read-excel-file/types';
import { getTemplatesMap } from '../../services/template-service';
import { getBatchesFromArray } from '../../utils/array-utils';
import { fileExists } from '../../utils/file-utils';
import { AssetSchema, getCollectionSchemas } from '../../services/schema-service';
import { getCollectionSchemas } from '../../services/schema-service';
import { isValidAttribute, typeAliases } from '../../utils/attributes-utils';
import { CliConfig } from '../../types/cli-config';
import { AssetSchema, CliConfig } from '../../types';
import { TransactResult } from '@wharfkit/session';
import { BaseCommand } from '../../base/BaseCommand';
import { readExcelContents } from '../../utils/excel-utils';
import { MintRow } from '../../types';

const templateField = 'template';
const amountField = 'amount';
const ownerField = 'owner';

type MintRow = {
schema: AssetSchema;
templateId: string;
amount: number;
owner: string;
mintActionData: MintData;
};

export default class MintCommand extends BaseCommand {
static description = 'Mints assets in batches using a spreadsheet.';

Expand Down Expand Up @@ -68,22 +60,21 @@ export default class MintCommand extends BaseCommand {
ux.action.stop();

// Read XLS file
if (!fileExists(mintsFile)) {
this.error('XLS file not found!');
}

ux.action.start('Reading mints in file');
const sheetNames = await readSheetNames(mintsFile);
const sheets = await Promise.all(sheetNames.map((name) => readXlsxFile(mintsFile, { sheet: name })));

const mintRows: MintRow[] = [];
for (let i = 0; i < sheetNames.length; i++) {
const sheet = sheets[i];
const schemaName = sheetNames[i].trim();
const schema = schemasMap[schemaName];
mintRows.push(...(await this.getMintRows(sheet, schema, config, ignoreSupply)));
try {
ux.action.start('Reading mints in file');
const sheets = await readExcelContents(mintsFile);
for (let i = 0; i < sheets.length; i++) {
const { name, rows } = sheets[i];
const schemaName = name.trim();
const schema = schemasMap[schemaName];
mintRows.push(...(await this.getMintRows(rows, schema, config, ignoreSupply)));
}
} catch (error: any) {
this.error(`Error reading file: ${error.message}`);
} finally {
ux.action.stop();
}
ux.action.stop();

// Create table columns and print table
const columns: any = {
Expand Down
2 changes: 1 addition & 1 deletion src/commands/config/auth.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Command } from '@oclif/core';
import { SettingsConfig } from '../../types/cli-config';
import { SettingsConfig } from '../../types';
import { readConfiguration } from '../../utils/config-utils';
import { getSession } from '../../services/antelope-service';
import { removeDir } from '../../utils/file-utils';
Expand Down
2 changes: 1 addition & 1 deletion src/commands/config/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { configFileExists, getSessionDir, removeConfigFile, writeConfiguration }

import { getChainId, validateExplorerUrl, validateAtomicAssetsUrl } from '../../utils/config-utils';
import { getSession } from '../../services/antelope-service';
import { SettingsConfig } from '../../types/cli-config';
import { SettingsConfig } from '../../types';
import { input, select } from '@inquirer/prompts';

interface Preset {
Expand Down
2 changes: 1 addition & 1 deletion src/commands/config/set.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Args, Command, ux } from '@oclif/core';
import { SettingsConfig } from '../../types/cli-config';
import { SettingsConfig } from '../../types';
import { readConfiguration, validate, writeConfiguration } from '../../utils/config-utils';

export default class SetCommand extends Command {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import { Args, Flags, ux } from '@oclif/core';
import { getTemplatesForCollection, getTemplatesFromSchema } from '../../services/template-service';
import { BaseCommand } from '../../base/BaseCommand';
import writeXlsxFile from 'write-excel-file/node';
import { AssetSchema, getCollectionSchemas, getSchema } from '../../services/schema-service';
import { getCollectionSchemas, getSchema } from '../../services/schema-service';
import { ITemplate } from 'atomicassets/build/API/Explorer/Objects';
import { getXlsType, transformValueToType } from '../../utils/attributes-utils';
import { fileExists } from '../../utils/file-utils';
import { AssetSchema } from '../../types';

const headers = [
{
Expand All @@ -19,7 +20,7 @@ const headers = [
},
];

export default class GenerateMintMetadataCommand extends BaseCommand {
export default class GenerateMintFileCommand extends BaseCommand {
static examples = [
{
command: '<%= config.bin %> <%= command.id %> mints.xlsx -c alpacaworlds -s thejourney',
Expand Down Expand Up @@ -55,7 +56,7 @@ export default class GenerateMintMetadataCommand extends BaseCommand {
};

public async run(): Promise<void> {
const { flags, args } = await this.parse(GenerateMintMetadataCommand);
const { flags, args } = await this.parse(GenerateMintFileCommand);
const config = await this.getCliConfig();

const output = args.output;
Expand Down
Loading

0 comments on commit 5e89031

Please sign in to comment.