How to call an hardhat plugin in a hardhat task? - javascript

I'm trying to create an hardhat task calling an hardhat extension, i'm using nodejs spawn but It doesn't work :/
How can I get this working ?
./tasks/checkk.js
const fs = require('fs');
const { spawn } = require('node:child_process')
task("checkk", "check contract's code on etherscan")
.addPositionalParam("myContract")
.setAction(async (taskArgs, hre) => {
const argsFile = `../args/${taskArgs.myContract}.js`
// after this line this is pseudo code only, nothing works...
const address = fs.readFile(`./addresses/${taskArgs.myContract}_${hre.network.name}_ADDRESS.txt`, 'utf-8')
const myCommand = `npx hardhat verify --network ${hre.network.name} ${address} --constructor-args ${argsFile}`
const command = spawn('myCommand', {
stdio: 'inherit',
shell: true
})
command.stdout.on('data', (output) => {
console.log("Output: ", output.toString())
})
})

Ok, hre.run is what I needed.
const fs = require('fs');
task("checkk", "check contract's code on etherscan : checkk MyContract --network MyNetwork")
.addPositionalParam("myContract")
.setAction(async (taskArgs, hre) => {
const CONTRACT_ARGUMENTS = require(`../args/${taskArgs.myContract}.js`)
const address = fs.readFileSync(`./addresses/${taskArgs.myContract}_${hre.network.name}_ADDRESS.txt`, "utf8")
await hre.run("verify:verify", {
address: address,
constructorArguments: CONTRACT_ARGUMENTS,
});
})

Related

Nodejs child_proccess.spawn no output using stdio: 'inherit'

I'm using node.js child_proccess.spawn() in order to execute few command lines in CMD and get the output.
I have encountered few issues:
When i'm trying to spawn the proccess witout stdio: 'inherit' option - The CMD freezes after executing the last command and won't print out the results.
When I add the stdio: 'inherit' option, I get the results printed to my terminal but I cant catch the output with child.stdout.on..
Is there any possible way to capture the terminal output or to avoid the proccess from being stuck?
function executeCommands (){
const firstCommand = 'do something1'
const secondCommand = 'do something2'
const thirdCommand = 'do something3'
let child = require('child_process').spawn(`${firstCommand} && ${secondCommand} &&
${thirdCommand}`, [], {shell: true,stdio: 'inherit'})
child.stdout.setEncoding('utf8')
child.stdout.on('data', (data) => {
console.log('stdout',data)
})
child.stdio.on('data', (data) => {
console.log('stdio',data)
})
child.stderr.on('data', (data) => {
console.log('stderr',data.toString())
})
}
Use child_process
const { execSync } = require("node:child_process");
const npmVersion = execSync("npm -v", { encoding: "utf-8" });
console.log(npmVersion);
// 8.15.0
if you want to use spawnSync
const { spawnSync } = require("node:child_process");
const npmVersion = spawnSync("npm", ["-v"], { encoding: "utf-8" });
console.log(npmVersion.stdout);
// 8.15.0

ValidationError > s.string Expected a string primitive Received: | undefined

Im using discord js to make a multi-purpose discord bot for my server, but its giving me this error:
ValidationError: Expected a string primitive
It was working fine yesterday but i forgot to save something and i dont know what.
const fs = require('node:fs');
const path = require('node:path');
const {
Client,
GatewayIntentBits,
Partials,
Collection,
} = require("discord.js");
const { Player } = require('discord-player');
const { Routes } = require('discord-api-types/v10');
const { token, prefix, guildId, clientId } = require('./config.json');
const { REST } = require('#discordjs/rest');
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMembers,
GatewayIntentBits.MessageContent,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.GuildPresences,
GatewayIntentBits.GuildVoiceStates
],
partials: [
Partials.Channel,
Partials.Message,
Partials.User,
Partials.GuildMember,
],
});
client.player = new Player(client, {
ytdlOptions: {
quality: "highestaudio",
highWaterMark: 1 << 25
}
});
module.exports = client;
// command handler
//slash commands
const slashCommands = [];
client.slashCommands = new Collection();
const commandsPath = path.join(__dirname, "commands"); // E:\yt\discord bot\js\intro\commands
const slash_commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('S.js'));
for(const file of slash_commandFiles)
{
const filePath = path.join(commandsPath, file);
const command = require(filePath);
client.slashCommands.set(command.data.name, command);
slashCommands.push(command.toJSON());
}
console.log(slashCommands);
//message commands
client.messageCommands = new Collection();
const message_commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('M.js'));
for (const file of message_commandFiles) {
const filePath = path.join(commandsPath, file);
const command = require(filePath);
// Set a new item in the Collection
// With the key as the command name and the value as the exported module
client.messageCommands.set(command.Name, command);
}
//event handler
const eventsPath = path.join(__dirname, 'events');
const eventFiles = fs.readdirSync(eventsPath).filter(file => file.endsWith('.js'));
for (const file of eventFiles) {
const filePath = path.join(eventsPath, file);
const event = require(filePath);
if (event.once) {
client.once(event.name, (...args) => event.execute(...args));
} else {
client.on(event.name, (...args) => event.execute(...args));
}
}
// messageCommand handler
client.on('messageCreate', (message) => {
const args = message.content.slice(prefix.length).split(' ');
const command = args[0];
if (client.messageCommands.get(command)) {
let Command = client.messageCommands.get(command);
Command.execute(message);
}
});
client.on('ready', () => {
const rest = new REST({ version: '9' }).setToken(token);
rest.put(Routes.applicationGuildCommands(clientId, guildId),
{ body: slashCommands })
.then(() => console.log('Successfully updated commands for guild ' + guildId))
.catch(console.error);
console.log('bot is online!');
client.user.setStatus('idle');
});
client.login(token);
im sure there's nothing wrong with any of the command files because it was working fine yesterday.
there's 100% an error in this line slashCommands.push(command.toJSON()); but I cant seem to fix it. The command.toJSON() console logs just fine but gives an error while trying to push into the list
Ran into the same issue, turns out options (i.e. addUserOption) require a description. Point is it's really confusing as this error shows up when doing command.data.toJSON(). If you are dynamically loading the command files as described in the guide and running into this issue, then try manually doing a require to trigger the validation beforehand.
Try using command.data.toJSON() as command is a nested object with a data and an execute key.
I've fixed it, there was a url in the json which seemed to be causing some issue, I removed the file with the url and its working now

"TypeError : Cannot read property 'address' of undefined" i receive this error after lunch the deploy in the testnet, but in localhost works

i receive this error TypeError : Cannot read property 'address' of undefined after lunched npx hardhat run scripts/deploy.js --network goerli, but the same command in localhost works well, why?
hardhat.config.js
require('dotenv').config();
require("#nomiclabs/hardhat-ethers");
const { API_URL, PRIVATE_KEY } = process.env;
module.exports = {
solidity: '0.8.4',
defaultNetwork: "goerli",
networks: {
hardhat: {},
goerli: {
url: API_URL,
accounts: [`0x${PRIVATE_KEY}`]
}
},
};
deploy.js
the error seems to be here, but i don't get why lunching npx hardhat run scripts/deploy.js works well and with goerly (or other testnet not)
if i write console.log(accounts[0].address); console.log(accounts[1].address); , i get the log only of the first one!
const { ethers } = require("hardhat");
const main = async () => {
let accounts;
accounts = await ethers.getSigners();
const OWNERS = [
accounts[0].address,
accounts[1].address,
accounts[2].address
]
const NUM_CONFIRMATIONS = 2
const MultiSig = await ethers.getContractFactory("MultiSig");
const multiInstance = await MultiSig.deploy(OWNERS, NUM_CONFIRMATIONS);
const TestContract = await ethers.getContractFactory("TestContract");
const testContract = await TestContract.deploy("msg");
await multiInstance.deployed();
await testContract.deployed();
console.log('multisig contract address: ', multiInstance.address);
console.log('test contract address: ', testContract.address);
};
const runMain = async () => {
try {
await main();
process.exit(0);
} catch (error) {
console.error(error);
process.exit(1);
}
};
runMain();
maybe i got it, i added only 1 private key, i have to add more in the "accounts"array

Heroku: how to have it access multiple .js files

I'm getting this error message on heroku and I think I'm getting it cause of Procfile.
I'm using Worker at the moment, but I'm trying to figure out how to have heroku access both index.js and ping.js. Unless I'm reading the error message completely wrong and this could be a different issue. Any help is appreciated!
EDIT:
Here's my code for index.js
const Discord = require('discord.js');
const music = require('#koenie06/discord.js-music');
const fs = require('fs');
const { dir } = require('console');
const bot = new Discord.Client({
shards: "auto",
intents: [
Discord.Intents.FLAGS.GUILDS,
Discord.Intents.FLAGS.GUILD_MESSAGES,
Discord.Intents.FLAGS.GUILD_MESSAGE_REACTIONS,
Discord.Intents.FLAGS.DIRECT_MESSAGES,
Discord.Intents.FLAGS.GUILD_VOICE_STATES
]
});
bot.commands = new Discord.Collection();
bot.aliases = new Discord.Collection();
//Command handler and aliases
fs.readdirSync('./commands/').forEach(dir => {
//in the commands folder, we gonna check for the category
fs.readdir(`./commands/${dir}`, (err, files) => {
//console log error(catch error)
if(err)throw err;
//checking if the files ends with .js if its a javascript file
var jsFiles = files.filter(f => f.split('.').pop() === 'js');
//if there is no commands in the file it will return
if(jsFiles.length <= 0) {
console.log("Can't find any commands");
return;
}
jsFiles.forEach(file => {
//console the loaded commands
var fileGet = require(`./commands/${dir}/${file}`);
console.log(`[COMMAND HANDLER] - File ${file} was loaded`);
//gonna let the commands run
try {
bot.commands.set(fileGet.help.name, fileGet);
// it search in the commands folder if there is any aliases
fileGet.help.aliases.forEach(alias => {
bot.aliases.set(alias, fileGet.help.name);
})
} catch(err) {
//catch error in console
return console.log(err);
}
})
})
})
/**
* ECHO STUFF
*/
//slash command to echo
bot.on('ready', async () => {
bot.user.setPresence({ activities: [{ name: "Tedi", type: "WATCHING"}] });
console.log("bye");
const data = {
name: 'echo',
description: 'Echo your text',
options: [{
name: 'text',
type: 'STRING',
description: 'The user input',
required: true,
}],
};
const command = await bot.guilds.cache.get('872986148681703444')?.commands.create(data);
})
bot.on('messageCreate', async message => {
if(message.author.bot || message.channel.type == 'DM') return
let prefix = '~'
let messageArray = message.content.split(' ');
let cmd = messsageArray[0];
let args = messageArray.slice(1);
//it will make the cmd work with his original name and his aliases
let commands = bot.commands.get(cmd.slice(prefix.length)) || bot.commands.get(bot.aliases.get(cmd.slice(prefix.length)));
if(commands) {
if(!message.content.startsWith(prefix)) return
commands.run(bot, message, args, prefix);
}
})
//interactionCreate for echo slash command
bot.on('interactionCreate', async interaction => {
/**
* isButton() used to check if its a button
* isCommand() used to check if its a slash command
* isSelectMenu() used to check if its a dropdown menu
* isMessageComponent()
*/
if(interaction.isCommand()) {
if(interaction.commandName === 'echo') {
const text = interaction.options.getString('text');
await interaction.reply({ content: text, ephemeral: false}); //if ephemeral if true, it would make the slash command private
}
}
})
bot.login(process.env.token);
Here is my ping.js
const Discord = require("discord.js");
module.exports.run = async (Client, message, args, prefix) => {
message.channel.send("pong")
}
module.exports.help = {
name: "ping",
aliases: ["p"]
}
This error is not because of Heroku, it's basically because there is a file in your command handler that doesn't have a name while handling it, as example like this code over here:
const Discord = require("discord.js");
module.exports.run = async (Client, message, args, prefix) => {
message.channel.send("pong")
}
module.exports.help = {
// here the name isn't included
aliases: ["p"]
}
// so just check if you have a file without a name while handling it and put a name, and if you don't want aliases make it `aliases: []`
This command handler should be like thisCommands Folder commands > Subfolder e.g. Moderation > kick.jsThats how it works, also thank you for watching my videos, I'm UltraX :)

Discord bot: Command Handler alias for command name

I am working on a Discord bot, and trying to improve my already functioning command handler.
I have a folder, and every file is an extra command. I want to expand the system, so I have alias name for the same command, e.g. I want my clearchat command to function with /clearchat or with /cc, but I dont want to create just another file and copy the code. This is what I have:
// I left out the other imports etc.
client.commands = new Discord.Collection();
// Reading commands-folder
const commandFiles = fs.readdirSync("./commands/").filter(file => file.endsWith(".js"));
for (const file of commandFiles) {
const command = require(`./commands/${file}`);
client.commands.set(command.name, command);
}
client.on("message", msg => {
if (msg.content.startsWith(config.prefix) && !msg.author.bot && msg.guild) {
const args = msg.content.slice(config.prefix.length).split(" ");
const command = args.shift().toLowerCase();
if (client.commands.find(f => f.name === command)) {
client.commands.get(command).execute(client, msg, args);
}
}
});
and then a command file inside the commands-folder:
module.exports = {
name: "clearchat",
execute(client, msg, args) {
if (msg.member.hasPermission("ADMINISTRATOR")) {
msg.channel.messages.fetch({limit: 99}).then(messages => {
msg.channel.bulkDelete(messages);
});
}
}
}
(I know it only deletes 100 messages max, I am fine with that)
I image something in changing a few lines in my client.on("message) function, and just having to write in the clearchat.js file a line like name: ["clearchat", "cc", ...] where I can go writing as much aliases as I want.
Thanks in advance!
First, you'll have to create an array with the aliases in your command.
module.exports = {
name: "clearchat",
aliases: ["cc"],
execute(client, msg, args) {
}
}
Then, the same you did with commands, create a Collection for the aliases.
client.aliases = new Discord.Collection()
And finally, bind the alias to the command:
if (command.aliases) {
command.aliases.forEach(alias => {
client.aliases.set(alias, command)
})
}
Now, when you want to execute a command, you'll have to check if it has an alias.
const commandName = "testcommand" // This should be the user's input.
const command = client.commands.get(commandName) || client.aliases.get(commandName); // This will return the command and you can proceed by running the execute method.
fs.readdir(`./commands/`, (error, files) => {
if (error) {return console.log("Error while trying to get the commmands.");};
files.forEach(file => {
const command = require(`./commands/${file}`);
const commandName = file.split(".")[0];
client.commands.set(commandName, command);
if (command.aliases) {
command.aliases.forEach(alias => {
client.aliases.set(alias, command);
});
};
});
});

Categories