Hello and thank you in advance!
const comprarCapsula = () => {
const compraCapsula = async () => {
console.log("Iniciando transacción...");
// ------------------------
const pago = web3.utils.toWei(precioFinal.toString(), 'ether');
// Mensaje de información
infoAlert();
// Petición al SC
const transaction = await contract.myFunction(cantidad, {
from: props.currentAccount,
value: pago.toString()}
).then((result) => {
console.log("RESULT:", result);
successAlert(result.tx);
}).catch((error) => {
console.error("TESTING: ", error.message);
errorAlert(error.message);
});
console.log("TRANS: ", transaction);
// ------------------------
}
contract && compraCapsula()
}
My application detects when I cancel the operation with MetaMask (error) but if the Smart Contract throws an error it is not picked up by the catch.
MetaMask - RPC Error: Internal JSON-RPC error.
Object { code: -32603, message: "Internal JSON-RPC error.", data: {…} }
Data: Object { code: 3, message: "execution reverted: Exception: must have minter role to mint"
Error "must have minter role to mint" its in my Smart Contract.
Why? I'm trying several ways to collect the RPC errors that Metamask throws but I can't find the way.
Could you check calling your contract function as such:
contract.myFunction.call
rather than
contract.myFunction
I had a similar problem when developing a contract. call can be used to see whether the function will throw an error - especially structural, modifier checking wise - but only using call will not invoke the full behaviour of the function. After checking for errors with call, you can call the function again.
Function calls with call enabled us to catch those kind of errors. I used such a structure then:
await contract.myFunction.call(`parameters...`)
.then(
contract.myFunction(`parameters...`)
)
Related
I am using Stripe's prebuilt checkout with react and firebase. The checkout process works fine and directs the user to the succes_url, but I would like to update a field under the user in the database as well. I don't understand how I can include a function that updates the DB that runs upon a successful checkout.
export const checkoutWithStripe = async(user) => {
const checkoutSessionsRef = collection(db, 'users', user.uid, 'checkout_sessions');
const singleCheckoutSessionRef = await addDoc(checkoutSessionsRef, {
price: 'price_xyz',
allow_promotion_codes: true,
success_url: `${window.location.origin}/dashboard/app?success=true`,
cancel_url: `${window.location.origin}/dashboard/app?canceled=true`
});
onSnapshot(singleCheckoutSessionRef, (snap) => {
const { error, url: checkoutUrl } = snap.data();
if (error) {
console.error(`An checkout error occured: ${error.message}`);
}
if (checkoutUrl) {
window.location.assign(checkoutUrl);
}
});
// TODO: Update user type in firebase from free to starter on successful checkout
};
Thankful for any help.
Update:
I solved it, in 2 parts.
In Stripe I created a new webhook that points to a exported firebase function (2) that fires when "checkout.session.completed" is fired.
In Firebase i created a function that listens for the "checkout.session.completed" event and then calls a function that updates the DB based on the user email that I get from the Stripe event.
This is the Firebase function that listens to the event:
/**
* A webhook handler function for the relevant Stripe events.
*/
exports.updateCustomer = functions.https.onRequest((req, resp) => {
functions.logger.log("updateCustomer body", req);
const relevantEvents = new Set([
'checkout.session.completed'
]);
let event;
// Instead of getting the `Stripe.Event`
// object directly from `req.body`,
// use the Stripe webhooks API to make sure
// this webhook call came from a trusted source
try {
event = stripe.webhooks.constructEvent(
req.rawBody,
req.headers['stripe-signature'],
endpointSecret
);
} catch (error) {
functions.logger.log(`Webhook Error: Invalid Secret`);
resp.status(401).send('Webhook Error: Invalid Secret');
return;
}
functions.logger.log("updateCustomer", event.type);
if (relevantEvents.has(event.type)) {
// logs.startWebhookEventProcessing(event.id, event.type);
try {
switch (event.type) {
case 'checkout.session.completed':
const session = event.data.object;
functions.logger.log("checkout.session.completed:", session);
updatePlan(session.customer_details.email);
break;
default:
functions.logger.log(`Unhandled event type ${event.type}`);
}
} catch (error) {
functions.logger.log(`Unhandled event error ${event.type}`);
resp.json({
error: 'Webhook handler failed. View function logs in Firebase.',
});
return;
}
}
// Return a response to Stripe to acknowledge receipt of the event.
resp.json({ received: true });
});
If you need to run some code when the Checkout Session is successful, then you should use Stripe webhooks and listen to the checkout.session.completed event. This is covered in the Stripe documentation.
I'm getting this error message : Invalid value for transfer when trying to use, for the very first time, the message-ports-reply-streams.
In preload.js I defined this api:
contextBridge.exposeInMainWorld(
"api", {
electronIpcPostMessage: (channel: string, message: any, transfer?: MessagePort[]) => {
ipcRenderer.postMessage(channel, message, transfer)
},
}
)
declare global {
interface Window {
api: {
electronIpcPostMessage: (channel: string, message: any, transfer?: MessagePort[]) => void;
}
}
And , following the example found here: https://www.electronjs.org/docs/latest/tutorial/message-ports#reply-streams , in the renderer React component I defined the streaming request as follows:
const Layers = () => {
const componentIsMounted = React.useRef(true)
React.useEffect(() => {
const cb = (event, args) => {
try {
if (componentIsMounted.current) {
console.log("react-leaflet-layers-args: ", args)
}
} catch (err) {
console.log("err: ", err)
}
}
const makeStreamingRequest = (element, cb) => {
// MessageChannels are lightweight--it's cheap to create a new one for each request.
const { port1, port2 } = new MessageChannel()
// We send one end of the port to the main process ...
window.api.electronIpcPostMessage(
'give-me-a-stream',
{ element, count: 10 },
[port2]
)
// ... and we hang on to the other end.
// The main process will send messages to its end of the port,
// and close it when it's finished.
port1.onmessage = (event) => {
cb(event.data)
}
port1.onclose = () => {
console.log('stream ended')
}
}
makeStreamingRequest(42, (data) => {
console.log('got response data:', event.data)
})
// We will see "got response data: 42" 10 times.
return () => { // clean-up function
componentIsMounted.current = false
window.api.electronIpcRemoveListener(
"give-me-a-stream",
cb,
)
}
}, [])
As said, when running Electron-React app the error message I get when accessing the page rendered by that component, is : Invalid value for transfer .
From this StackOverflow question : Invalid value for transfer while using ipcRenderer.postMessage of electron, it seems that I'm not the only one stumbling on this type of error, but I didn't find any solutions yet.
What am I doing wrongly or missing? How to solve the problem?
My objective is to send, better in a streaming fashion, a very big geojson file from the main process to the renderer process. That's why I thought to try to use ipcRenderer.postMessage.
By the way, any other working solutions that accomplish this goal, are welcomed.
Other info:
electron: v. 16
node: v. 16.13.0
O.S: Ubuntu 20.04
Looking forward to hints and help
I also encountered the same problem. In https://www.electronjs.org/docs/latest/api/context-bridge, it is mentioned that the types of parameters, errors and return values in functions bound with contextBridge are restricted, and MessagePort is one of the types that cannot be transported, so it doesn't recognize the MessagePort you passed in and throw this error.
If you want to use MessageChannel for communication, you can provide some proxy functions through contextBridge in preload.js, call these functions in renderer.js and pass in copyable parameters.
Hope my answer helps you.
I'm calling a withdrawal method from a contract written in solidity from a react.js app using metamask. The transaction is failing and I don't know why. I think is something related to the gas fee because when I change it I get different errors. This is the react code:
contract.methods
.withdrawDividends()
.send({
from: userAddress,
value: availableToWithdraw,
})
.on("transactionHash", function (hash: string) {
console.log(hash);
})
.on(
"confirmation",
function (confirmationNumber: number, receipt: unknown) {
console.log(confirmationNumber);
console.log(receipt);
}
)
.on("receipt", function (receipt: unknown) {
// receipt example
console.log(receipt);
})
.on("error", function (error: unknown, receipt: unknown) {
// If the transaction was rejected by the network with a receipt, the second parameter will be the receipt.
console.log(error);
console.log(receipt);
});
This is my solidity method:
function withdrawDividends() public {
User storage user = users[_msgSender()];
uint256 totalAmount = getUserDividends(_msgSender());
require(totalAmount > 0, "User has no dividends");
user.checkpoint = block.timestamp;
(bool success, ) = _msgSender().call.value(totalAmount)("");
require(success, "Transfer failed.");
emit Withdrawn(_msgSender(), totalAmount);
}
The method is not crashing but I see the following error in metamask:
What I'm doing wrong? Is something related to the gas?
If you want your function to accept ETH value, it needs to have the payable modifier.
In your case:
function withdrawDividends() public payable {
You can read more about the payable modifier in the docs. It links to the receive function, which is a slightly different topic. But it also covers the payable modifier.
I have some code for discord.js that sends a user a DM when they join the server. They then have to enter the password given to them, and it will then give them a role that allows them access to channels.
const Discord = require('discord.js');
const client = new Discord.Client();
client.once('ready', () => {
console.log('Ready!');
});
client.on('guildMemberAdd', guildMember => {
console.log("Joined");
guildMember.send("Welcome to the server! Please enter the password given to you to gain access to the server:")
.then(function(){
guildMember.awaitMessages(response => message.content, {
max: 1,
time: 300000000,
errors: ['time'],
})
.then((collected) => {
if(response.content === "Pass"){
guildMember.send("Correct password! You now have access to the server.");
}
else{
guildMember.send("Incorrect password! Please try again.");
}
})
.catch(function(){
guildMember.send('You didnt input the password in time.');
});
});
});
client.login("token");
The thing is, I don't really know how to use the awaitResponses function. I do not know how to call it, because all the tutorials I find use it with message.member.
When I run my code, I get these three errors:
UnhandledPromiseRejectionWarning: TypeError: guildMember.awaitMessages is not a function
UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag --unhandled-rejections=strict (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.
I do not know what lines these are referring to, so I am very confused.
Here's a quick rundown on how awaitMessages works:
First of all, the .awaitMessages() function extends GuildChannel, meaning you had already messed up a little bit by extending the GuildMember object instead. - You could easily fetch a channel using
const channelObject = guildMember.guild.channels.cache.get('Channel ID Here'); // Gets a channel object based on it's ID
const channelObject = guildMember.guild.channels.cache.find(ch => ch.name === 'channel name here') // Gets a channel object based on it's name
awaitMessages() also gives you the ability to add a filter for a certain condition an input must have.
Let's take the freshly new member as an example. We could simply tell the client to only accept input from members who have the same id as the guildMember object, so basically only the new Member.
const filter = m => m.author.id === guildMember.id
Now, finally, after we've gathered all of the resources needed, this should be our final code to await Messages.
const channelObject = guildMember.guild.channels.cache.get('Channel ID Here');
const filter = m => m.author.id === guildMember.id
channelObject.awaitMessages(filter, {
max: 1, // Requires only one message input
time: 300000000, // Maximum amount of time the bot will await messages for
errors: 'time' // would give us the error incase time runs out.
})
To read more about awaitMessages(), click here!
I want it so my bot can only send embeds in specific channels with the permissions granted but if a user sends the message in a channel where the permissions are not granted the bot stops working and cuts off. I am trying to make it so a try catch works so even if an error is thrown it continues to work, the error I am getting is "UnhandledPromiseRejectionWarning: DiscordAPIError: Missing Permissions - I want to be able to ignore this error.
function catchErr (err, emessage, a){
console.log("Someone tried to use the embed in the");}
let args = message.content.slice(PREFIX.length).split(' ');
switch(args[0]){
case 'discordbot ':
try {
const discordbot = new Discord.MessageEmbed()
.setTitle('My Discord Bot*')
.addFields(
{ name: 'Test Bot:', value: 'Test' },
message.channel.send(discordbot );
} catch (err) {
catchErr(err, message);
}
.send returns a Promise, if you want to catch errors you can either go for Promise.catch or use async / await (this requires your top level function to be async)
// Using Promise.catch
const catchErr = err => {
console.log(err)
}
message.channel.send(embed).catch(catchErr)
// Using async / await
try {
await message.channel.send(embed)
} catch(err) {
catchErr(err)
}
function sendMessage(message,content){
const permissions = message.channel.permissionsFor(message.client.user);
if (permissions.has("SEND_MESSAGES")){
if(content){
message.channel.send(content);
}
}
else{
console.log("[ERR] no msg perms")
message.author.send("I can't send messages on this channel or guild!, Try another channel or contact the server staff to check bot's permissions.");
}
}