web3 metamask payment not selecting the right asset - web3js

I would like to create a button where people can click to make an pre set payment with Metamask.
This is what I have so far.
const contractAddress = '0x08ba0619b1e7a582e0bce5bbe9843322c954c340';
const reciever = '0x6B5e6761A9fa07573aD01aeEBc0B724bD3a2980a';
const ABI = [
{
"inputs": [
{ "internalType": "address", "name": "recipient", "type": "address" },
{ "internalType": "uint256", "name": "amount", "type": "uint256" }
],
"name": "transfer",
"outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
"stateMutability": "nonpayable",
"type": "function"
}
]
window.addEventListener('load',()=>{
(async ()=>{
let web3;
if(window.ethereum){
web3 = new Web3(window.ethereum);
await ethereum.enable();
if(window.ethereum.chainId == '0x38'){
const contract = new web3.eth.Contract(ABI, contractAddress);
const transfer = await contract.methods.transfer(reciever, 10);
const encodedABI = await transfer.encodeABI();
web3.eth.sendTransaction({
to: reciever,
from: ethereum.selectedAddress,
data: encodedABI,
})
} else {
ethereum.request({ method: 'wallet_switchEthereumChain', params:[{chainId: '0x38'}]})
}
}
})()
})
the part that's not working is, I want to make a BMON payment, but its not selecting BMON but just a random token.
This is what I get
This is what I need
I don't understand what I am doing wrong, I selected the right contract address and used the ABI from BMON, where is the part that selects BMON token here?

The problem was in the
const transfer = await contract.methods.transfer(reciever, 10);
needed to be
const transfer = await contract.methods.transfer(reciever, 10).call();

Related

Alexa Skill : How to invoke custom intent from a template?

I'm trying to create an alexa skill with the help of 'Survey' template, which uses personalization + voice recognition based auth.
personalization + voice recognition based auth works fine. I have added a new intent 'Introduce' which needs to be triggered based on utterance - 'introduce' but that isn't working as expected.
Alexa open my bot
-> (welcome note from alexa)
let's begin (invokes StartMyStandupIntentHandler intent and auth based on voice id)
-> Hello How can i help you?
introduce
-> doesn't invoke IntroduceHandler but i have IntentReflectorHandler that says : You just triggered the introduce intent. You're hearing this response because introduce does not have an intent handler yet.
index.js:
const LaunchRequestHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'LaunchRequest';
},
handle(handlerInput) {
const requestAttributes = handlerInput.attributesManager.getRequestAttributes();
const skillName = requestAttributes.t('SKILL_NAME');
const name = personalization.getPersonalizedPrompt(handlerInput);
var speakOutput = ""
if (name && name.length > 0) {
speakOutput = requestAttributes.t('GREETING_PERSONALIZED', skillName);
} else {
speakOutput = requestAttributes.t('GREETING', skillName);
}
const repromptOutput = requestAttributes.t('GREETING_REPROMPT');
return handlerInput.responseBuilder
.speak(speakOutput)
.reprompt(repromptOutput)
.getResponse();
},
};
const StartMyStandupIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'StartMyStandupIntent';
},
async handle(handlerInput) {
const requestAttributes = handlerInput.attributesManager.getRequestAttributes();
let speakOutput;
const name = personalization.getPersonalizedPrompt(handlerInput);
let response = handlerInput.responseBuilder;
if (name && name.length > 0) {
speakOutput = 'Hello '+ name +'! How can i help you?';
const upsServiceClient = handlerInput.serviceClientFactory.getUpsServiceClient();
let profileName
let profileEmail
try {
profileName = await upsServiceClient.getPersonsProfileGivenName();
profileEmail = await upsServiceClient.getProfileEmail();
} catch (error) {
return handleError(error, handlerInput)
}
const sessionAttributes = handlerInput.attributesManager.getSessionAttributes();
sessionAttributes.userEmail = profileEmail;
sessionAttributes.userName = profileName;
handlerInput.attributesManager.setSessionAttributes(sessionAttributes);
} else {
speakOutput = requestAttributes.t('PERSONALIZED_FALLBACK')
}
return response
.speak(speakOutput)
.withShouldEndSession(false)
.getResponse()
},
};
const Introduce_Handler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'Introduce'
},
handle(handlerInput) {
const responseBuilder = handlerInput.responseBuilder;
let say = 'Hi everyone, As the famous saying goes, \'The human voice is the most perfect instrument of all\', . ';
say += 'A very Warm greetings to all. ';
return responseBuilder
.speak(say)
.withShouldEndSession(false)
.getResponse();
},
};
/**
* Voice consent request - response is handled via Skill Connections.
* Hence we need to handle async response from the Voice Consent.
* The user could have accepted or rejected or skipped the voice consent request.
* Create your custom callBackFunction to handle accepted flow - in this case its handling identifying the person
* The rejected/skipped default handling is taken care by the library.
*
* #params handlerInput - the handlerInput received from the IntentRequest
* #returns
**/
async function handleCallBackForVoiceConsentAccepted(handlerInput) {
const upsServiceClient = handlerInput.serviceClientFactory.getUpsServiceClient();
let profileName = await upsServiceClient.getProfileEmail();
let profileEmail = await upsServiceClient.getPersonsProfileGivenName();
const sessionAttributes = handlerInput.attributesManager.getSessionAttributes();
sessionAttributes.userEmail = profileEmail;
sessionAttributes.userName = profileName;
handlerInput.attributesManager.setSessionAttributes(sessionAttributes);
// this is done because currently intent chaining is not supported from any
// Skill Connections requests, such as SessionResumedRequest.
const requestAttributes = handlerInput.attributesManager.getRequestAttributes();
const name = personalization.getPersonalizedPrompt(handlerInput);
let speakOutput = 'Hello '+ name +'! How can i help you?';
//let repromptOutput = requestAttributes.t('ABOUT_REPROMPT');
let response = handlerInput.responseBuilder;
return response
.speak(speakOutput)
.reprompt(speakOutput)
.getResponse()
}
Interaction model json:
{
"interactionModel": {
"languageModel": {
"invocationName": "my bot",
"modelConfiguration": {
"fallbackIntentSensitivity": {
"level": "LOW"
}
},
"intents": [
{
"name": "AMAZON.CancelIntent",
"samples": []
},
{
"name": "AMAZON.HelpIntent",
"samples": []
},
{
"name": "AMAZON.StopIntent",
"samples": []
},
{
"name": "AMAZON.NavigateHomeIntent",
"samples": []
},
{
"name": "GetCodeIntent",
"slots": [
{
"name": "MeetingCode",
"type": "AMAZON.NUMBER"
}
],
"samples": [
"My code is {MeetingCode}",
"The code is {MeetingCode}",
"{MeetingCode}"
]
},
{
"name": "GetReportIntent",
"slots": [
{
"name": "questionYesterday",
"type": "AMAZON.SearchQuery",
"samples": [
"{questionYesterday}"
]
},
{
"name": "questionToday",
"type": "AMAZON.SearchQuery",
"samples": [
"{questionToday}"
]
},
{
"name": "questionBlocking",
"type": "AMAZON.SearchQuery",
"samples": [
"{questionBlocking}"
]
}
],
"samples": [
"{questionToday} today",
"{questionYesterday} yesterday",
"yesterday {questionYesterday}",
"today {questionToday}"
]
},
{
"name": "AMAZON.FallbackIntent",
"samples": []
},
{
"name": "AMAZON.YesIntent",
"samples": []
},
{
"name": "AMAZON.NoIntent",
"samples": []
},
{
"name": "ResetPinIntent",
"slots": [],
"samples": [
"where do i get a pin",
"what is my pin",
"how do i get a pin",
"i need a new pin",
"i forgot my pin"
]
},
{
"name": "StartMyStandupIntent",
"slots": [],
"samples": [
"yes let's get started",
"yes let's begin",
"let's begin",
"let's get started"
]
},
{
"name": "Introduce",
"slots": [],
"samples": [
"introduce yourself",
"introduce",
"intro"
]
}
],
"types": []
},
"dialog": {
"intents": [
{
"name": "GetReportIntent",
"delegationStrategy": "ALWAYS",
"confirmationRequired": false,
"prompts": {},
"slots": [
{
"name": "questionYesterday",
"type": "AMAZON.SearchQuery",
"confirmationRequired": false,
"elicitationRequired": true,
"prompts": {
"elicitation": "Elicit.Slot.420907304064.1434077833163"
}
},
{
"name": "questionToday",
"type": "AMAZON.SearchQuery",
"confirmationRequired": false,
"elicitationRequired": true,
"prompts": {
"elicitation": "Elicit.Slot.173201382582.539843571833"
}
},
{
"name": "questionBlocking",
"type": "AMAZON.SearchQuery",
"confirmationRequired": false,
"elicitationRequired": true,
"prompts": {
"elicitation": "Elicit.Slot.173201382582.1204298947985"
}
}
]
}
],
"delegationStrategy": "ALWAYS"
},
"prompts": [
{
"id": "Elicit.Slot.288779318596.409557698368",
"variations": [
{
"type": "PlainText",
"value": "Alright, first question. What did you do yesterday?"
}
]
},
{
"id": "Elicit.Slot.288779318596.1420775370020",
"variations": [
{
"type": "PlainText",
"value": "Got it. What will you do today?"
}
]
},
{
"id": "Elicit.Slot.288779318596.88143460540",
"variations": [
{
"type": "PlainText",
"value": "Okay, last question. Is there anything blocking your progress?"
}
]
},
{
"id": "Elicit.Slot.420907304064.1434077833163",
"variations": [
{
"type": "PlainText",
"value": "What did you work on yesterday?"
}
]
},
{
"id": "Elicit.Slot.173201382582.539843571833",
"variations": [
{
"type": "PlainText",
"value": "What will you work on today?"
}
]
},
{
"id": "Elicit.Slot.173201382582.1204298947985",
"variations": [
{
"type": "PlainText",
"value": "What if anything is blocking your progress?"
}
]
}
]
}
}
I suspect you missed adding your intent handler to the Skill object. See this snipet from the Alexa documentation
let skill;
exports.handler = async function (event, context) {
console.log(`REQUEST++++${JSON.stringify(event)}`);
if (!skill) {
skill = Alexa.SkillBuilders.custom()
.addRequestHandlers(
LaunchRequestHandler,
StartMyStandupIntentHandler,
HelpIntentHandler,
CancelAndStopIntentHandler,
SessionEndedRequestHandler,
)
.addErrorHandlers(ErrorHandler)
.create();
}
const response = await skill.invoke(event, context);
console.log(`RESPONSE++++${JSON.stringify(response)}`);
return response;
};
You need to add the Introduce_Handler to the addRequestHandlers method call. Also, make sure to add it before the intent reflector handler. ASK will prioritize which handler is used based on the order they are added to the skill object. Your code will probably look something like this:
.addRequestHandlers(
LaunchRequestHandler,
AskWeatherIntentHandler,
Introduce_Handler,
HelpIntentHandler,
CancelAndStopIntentHandler,
SessionEndedRequestHandler,
IntentReflectorHandler
)

I can't retrieve consistent information from my solidity smart contract using react and web3

I try to interact with functions in my deployed contract using web3. It works fine to get information from metamask but it seems to return truncated value with my smart contract (?).
The request with await web3.eth.getAccounts() wotks fine, but the requests for the smart contract MyDeposit.methods.getBalance().call() and MyDeposit.methods.account().call()seem inconsistent.
here is a screen shot of html rendering
here is a screen sot of my console
I retrieve well my account (0x3B8F16325799ce799555243418df22C5c8e81f48) but I should have retrieved also 9000000000001 for MyDeposit.methods.getBalance and (0x3B8F16325799ce799555243418df22C5c8e81f48) for MyDeposit.methods.account. however, I just got (9) for MyDeposit.methods.getBalance and (0) for MyDeposit.methods.account. It looks like if only the first digit of good response was returned.
would be great if anyone could help. Txs
here is my code :
import React, { Component } from "react";
import Web3 from "web3";
import "./App.css";
import { TODO_LIST_ABI, TODO_LIST_ADDRESS, TODO_ENTER_YOUR_KEY } from "./config";
class App extends Component {
async UNSAFE_componentWillMount() {
await this.loadWeb3();
await this.loadBlockchainData();
}
async loadWeb3() {
if (window.ethereum) {
window.web3 = new Web3(window.ethereum);
await window.ethereum.enable();
} else if (window.web3) {
window.web3 = new Web3(window.web3.currentProvider);
} else {
window.alert("No ethereum broswer detected! You can check out MetaMask!");
}
}
async loadBlockchainData() {
const web3 = new Web3(
Web3.givenProvider ||
"https://goerli.infura.io/v3/" + TODO_ENTER_YOUR_KEY
);
const accounts = await web3.eth.getAccounts();
this.setState({ account: accounts[0] });
const MyDeposit = new web3.eth.Contract(TODO_LIST_ABI, TODO_LIST_ADDRESS);
console.log(MyDeposit);
const owners = await MyDeposit.methods.owner().call();
this.setState({ owner: owners[0] });
console.log("this.state.owner : " + this.state.owner);
await MyDeposit.methods.sendEther().call();
let balances = []
balances = await MyDeposit.methods.getBalance().call();
console.log(balances[0])
this.setState({ balance: balances[0] });
console.log(this.state.balance);
console.log("this.state.balance : " + this.state.balance);
}
constructor(props) {
super(props);
this.state = {
account:[],
balance: [],
owner: []
};
}
render() {
return (
<div>
<div className="container-fluid">
<div className="row">
<main
role="main"
className="col-lg-12 d-flex justify-content-center"
>
<div id="loader" className="text-center">
<p className="text-center">On progress...</p>
</div>
<div id="content">
<p> the account is : {this.state.account} </p>
<p> the balance is : {this.state.balance} </p>
<p> the owner is : {this.state.owner} </p>
<ul id="completedTaskList" className="list-unstyled"></ul>
</div>
</main>
</div>
</div>
</div>
);
}
}
export default App;
here is the config.js with smart contract ABI
export const TODO_LIST_ADDRESS = "0xe78a5c60fa13BBB677d4c1D37a007ed59bE5Ca2e";
export const TODO_ENTER_YOUR_KEY = "enter your infura key for testing";
export const TODO_LIST_ABI = [
{
"inputs": [],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [],
"name": "getBalance",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "owner",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "sendEther",
"outputs": [],
"stateMutability": "payable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address payable",
"name": "recipient",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"name": "transferEther",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
}
]
owner and balancese had to be declared in the array. It's now OK.
I wrote:
const owners = [await MyDeposit.methods.owner().call()];
const balances = [await MyDeposit.methods.getBalance().call()];
instead of previous:
const owners = await MyDeposit.methods.owner().call();
const balances = await MyDeposit.methods.getBalance().call();
It's now OK. I get the full field.

Authenticated user shows up in console.log but can't access the object

I'm using Supabase for authentication and I get a user object when logging in.
This is how it looks like:
{
"id": "cb43b195-22cc-48c8-946a-d323f70165bd",
"aud": "authenticated",
"role": "authenticated",
"email": "joe#*******.com",
"email_confirmed_at": "2022-01-26T18:34:31.105402Z",
"phone": "",
"confirmed_at": "2022-01-26T18:34:31.105402Z",
"last_sign_in_at": "2022-02-01T18:00:27.998776Z",
"app_metadata": {
"provider": "github",
"providers": [
"github"
]
},
"user_metadata": {
"avatar_url": "https://avatars.githubusercontent.com/u/93337091?v=4",
"email": "joe#*******.com",
"email_verified": true,
"full_name": "Joe",
"iss": "https://api.github.com",
"name": "Joe",
"preferred_username": "joe",
"provider_id": "93337091",
"sub": "93337091",
"user_name": "joe"
},
"identities": [
{
"id": "93337091",
"user_id": "cb43b195-22cc-48c8-946a-d323f70165bd",
"identity_data": {
"avatar_url": "https://avatars.githubusercontent.com/u/93337091?v=4",
"email": "joe#*******.com",
"email_verified": true,
"full_name": "Joe",
"iss": "https://api.github.com",
"name": "Joe",
"preferred_username": "joe",
"provider_id": "93337091",
"sub": "93337091",
"user_name": "joe"
},
"provider": "github",
"last_sign_in_at": "2022-01-26T18:34:31.102361Z",
"created_at": "2022-01-26T18:34:31.102403Z",
"updated_at": "2022-01-26T18:34:31.102403Z"
}
],
"created_at": "2022-01-26T18:34:31.098348Z",
"updated_at": "2022-01-26T18:37:12.766+00:00",
"username": "joe",
"avatar_url": "0.181358731179603.png",
"website": null }
I'm trying to access any property but for instance, if I try to render {user.username} I get a "Cannot read username property of null" error.
Any idea why that happens?
This is the context that gives the user info - I'm using it to provide the auth data:
import { createContext, useState, useEffect, useContext } from "react";
import { supabase } from "../utils/supabase";
import { useRouter } from "next/router";
const Context = createContext();
const Provider = ({ children }) => {
const router = useRouter();
const [user, setUser] = useState(supabase.auth.user());
useEffect(() => {
const getUserProfile = async () => {
const sessionUser = supabase.auth.user();
if (sessionUser) {
const { data: profile } = await supabase
.from("profiles")
.select("*")
.eq("id", sessionUser.id)
.single();
setUser({
...sessionUser,
...profile,
});
}
};
getUserProfile();
supabase.auth.onAuthStateChange(() => {
getUserProfile();
});
}, []);
const login = async () => {
await supabase.auth.signIn({
provider: "github",
});
};
const logout = async () => {
await supabase.auth.signOut();
setUser(null);
router.push("/");
};
const exposed = {
user,
login,
logout,
};
return <Context.Provider value={exposed}>{children}</Context.Provider>;
};
export const useUser = () => useContext(Context);
export default Provider;
Thanks!
Could be because you are trying to access the user information before the API returns the data. In the component you are rendering the user data, check if the user exists first before returning your component.
if(!user) {
return <p>Loading...</p>
}
I had a similar issue and changing {user.username} to {user?.username} fixed the error for me. I am not exactly sure why, but hopefully this might help somebody.

React + fetch: adding extra characters and backslashes to my url

I have this code in React 17
useEffect(() => {
getLocalJson('../json/login/login.json', props.headers)
.then(resp => {
setFields(resp);
});
}, [props.headers]);
And the getLocalJson method is in a different file:
export const getLocalJson = async (url, headers) => {
console.log(url)
const resp = await fetch(url, {'headers': headers});
const json = await resp.json();
return json;
}
However the call to load the local JSON file from the public folder is:
Request URL: http://localhost:3000/json/login/%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5C%5Cdx%5Cjson%5Clogin%5Clogin.json
Ths is the JSON
[
{
"order": 0,
"systemName": "title",
"friendlyName": "Login",
"dataType": {
"type": "TITLE"
}
},
{
"order": 1,
"required": true,
"systemName": "username",
"friendlyName": "Username",
"errorMsg": "Invalid username",
"dataType": {
"type": "TEXT"
}
},
{
"order": 2,
"required": true,
"systemName": "password",
"friendlyName": "Password",
"errorMsg": "Invalid password",
"dataType": {
"type": "PASSWORD"
}
},
{
"order": 3,
"systemName": "title",
"friendlyName": "Login",
"dataType": {
"type": "BUTTON",
"submit": true
}
}
]
And it makes the call over and over and over
This exact code works on my ubuntu dev box, but is failing as abovw on my windows box
I think there is some issue with the way you are passing down the headers, look into the documentation to have a better idea.
Put your function in the body of your component where you're using useEffect and wrap it with useCallback like this:
const getLocalJson = useCallback( async (url, headers) => {
console.log(url)
const resp = await fetch(url, {'headers': headers});
const json = await resp.json();
return json;
},[])

Can't access the nested objects but can render the non-nested ones from API (using React hooks)

I'm a bit stumped on this problem I encountered trying to render the data from an API. Weird thing is I successfully fetched the data and I can render the values of properties in the array but the moment it becomes a nested property within an array it returns undefined. Do you by any chance know why?
location[0] + '&lon=' +
location[1] + '&APPID=8e6150cf719d58fc8062d507eaba92c0'
const [data, loading] = useFetch(url);
console.log(data.main.temp) // returns undefined
console.log(data.name) // logs name
The useFetch() is the following:
useEffect(() => {
async function fetchUrl() {
const response = await fetch(url);
const json = await response.json();
setData(json);
setLoading(false);
}
fetchUrl();
}, [url]);
return [data, loading];
}
export { useFetch };
The error message is:
TypeError: Cannot read property 'temp' of undefined
Data fetched looks like this:
{
"coord": {
"lon": 2.18,
"lat": 41.42
},
"weather": [
{
"id": 800,
"main": "Clear",
"description": "clear sky",
"icon": "01n"
}
],
"base": "stations",
"main": {
"temp": 293.81,
"pressure": 1013,
"humidity": 77,
"temp_min": 292.04,
"temp_max": 294.82
},
"visibility": 10000,
"wind": {
"speed": 2.6,
"deg": 120
},
"clouds": {
"all": 0
},
"dt": 1561061585,
"sys": {
"type": 1,
"id": 6414,
"message": 0.0074,
"country": "ES",
"sunrise": 1561004254,
"sunset": 1561058875
},
"timezone": 7200,
"id": 3124932,
"name": "el Clot",
"cod": 200
}

Resources