@holographxyz/cli
Version:
Holograph operator CLI
178 lines (177 loc) • 7.54 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const fs = tslib_1.__importStar(require("fs-extra"));
const inquirer = tslib_1.__importStar(require("inquirer"));
const core_1 = require("@oclif/core");
const ethers_1 = require("ethers");
const config_1 = require("../../utils/config");
const validation_1 = require("../../utils/validation");
const environment_1 = require("@holographxyz/environment");
const contracts_1 = require("../../utils/contracts");
const networks_1 = require("@holographxyz/networks");
const node_path_1 = tslib_1.__importDefault(require("node:path"));
class Nft extends core_1.Command {
static LAST_BLOCKS_FILE_NAME = 'blocks.json';
static description = 'Check the status of an NFT across all networks defined in the config.';
static examples = [
'$ <%= config.bin %> <%= command.id %> --address="0x5059bf8E4De43ccc0C27ebEc9940e2310E071A78" --id=1',
];
static flags = {
address: core_1.Flags.string({
description: 'The address of contract to check status of',
}),
id: core_1.Flags.string({
description: 'Token ID to check',
}),
output: core_1.Flags.string({
options: ['csv', 'json', 'yaml', ''],
description: 'Define table output type',
default: 'yaml',
}),
};
tokenId;
contractAddress;
registryAddress;
supportedNetworks = [];
providers = {};
holograph;
registryContract;
erc721Contract;
async initializeEthers(configFile, environment) {
for (let i = 0, l = this.supportedNetworks.length; i < l; i++) {
const network = this.supportedNetworks[i];
const rpcEndpoint = configFile.networks[network].providerUrl;
const protocol = new URL(rpcEndpoint).protocol;
switch (protocol) {
case 'https:':
this.providers[network] = new ethers_1.ethers.providers.JsonRpcProvider(rpcEndpoint);
break;
case 'wss:':
this.providers[network] = new ethers_1.ethers.providers.WebSocketProvider(rpcEndpoint);
break;
default:
throw new Error('Unsupported RPC provider protocol -> ' + protocol);
}
}
const holographABI = await fs.readJson(node_path_1.default.join(__dirname, `../../abi/${environment}/Holograph.json`));
this.holograph = new ethers_1.ethers.Contract(contracts_1.HOLOGRAPH_ADDRESSES[environment], holographABI, this.providers[this.supportedNetworks[0]]);
const holographRegistryABI = await fs.readJson(node_path_1.default.join(__dirname, `../../abi/${environment}/HolographRegistry.json`));
this.registryAddress = await this.holograph.getRegistry();
this.registryContract = new ethers_1.ethers.Contract(this.registryAddress, holographRegistryABI, this.providers[this.supportedNetworks[0]]);
const erc721ABI = await fs.readJson(node_path_1.default.join(__dirname, `../../abi/${environment}/ERC721Holograph.json`));
this.erc721Contract = new ethers_1.ethers.Contract(this.contractAddress, erc721ABI, this.providers[this.supportedNetworks[0]]);
}
async validateContractAddress() {
if (this.contractAddress === '') {
const prompt = await inquirer.prompt([
{
name: 'contractAddress',
message: 'Enter the contract address to check status of',
type: 'string',
validate: async (input) => {
return validation_1.addressValidator.test(input) ? true : 'Input is not a valid contract address';
},
},
]);
this.contractAddress = prompt.contractAddress;
}
if (!validation_1.addressValidator.test(this.contractAddress)) {
throw new Error(`Invalid contract address: ${this.contractAddress}`);
}
}
async validateTokenId() {
if (this.tokenId === '') {
const prompt = await inquirer.prompt([
{
name: 'tokenId',
message: 'Provide a token ID to get status for',
type: 'string',
validate: async (input) => {
return validation_1.tokenValidator.test(input) ? true : 'Input is neither a valid number or 32-byte hex string';
},
},
]);
this.tokenId = prompt.tokenId;
}
if (!validation_1.tokenValidator.test(this.tokenId)) {
this.error('Invalid token ID');
}
}
/**
* Command Entry Point
*/
async run() {
this.log('Loading user configurations...');
const environment = (0, environment_1.getEnvironment)();
const { configFile } = await (0, config_1.ensureConfigFileIsValid)(this.config.configDir, undefined, false);
this.log('User configurations loaded.');
const { flags } = await this.parse(Nft);
this.contractAddress = flags.address || '';
this.tokenId = flags.id || '';
await this.validateContractAddress();
await this.validateTokenId();
this.supportedNetworks = Object.keys(configFile.networks);
await this.initializeEthers(configFile, environment);
// data we want
// network -- deployed -- valid -- address -- explorer link
const data = [];
for (const network of this.supportedNetworks) {
const d = {
network,
deployed: false,
valid: false,
exists: false,
owner: '0x',
link: '',
};
const provider = this.providers[network];
const registry = this.registryContract.connect(provider);
const erc721 = this.erc721Contract.connect(provider);
const code = await provider.getCode(this.contractAddress, 'latest');
const token = ethers_1.ethers.BigNumber.from(this.tokenId);
if (code === '0x') {
// do nothing
}
else {
d.deployed = true;
d.valid = await registry.isHolographedContract(this.contractAddress);
if (d.valid) {
d.exists = await erc721.exists(token.toHexString());
if (d.exists) {
d.owner = await erc721.ownerOf(token.toHexString());
d.link = (networks_1.networks[network].explorer || '') + '/token/' + this.contractAddress + '?a=' + token.toString();
}
}
}
data.push(d);
}
core_1.CliUx.ux.table(data, {
network: {
header: 'Network',
},
deployed: {
header: 'Deployed',
},
valid: {
header: 'Valid',
},
exists: {
header: 'Exists',
},
owner: {
header: 'Owner',
},
link: {
header: 'Explorer Link',
},
}, {
printLine: this.log.bind(this),
'no-truncate': true,
'no-header': false,
output: flags.output,
});
this.exit();
}
}
exports.default = Nft;