web3js says method is not found in ERC20 contract - javascript

The Open Zeppelin ERC20 contract has a name(), symbol, and totalSupply() function. This is my smart contract that inherits the ERC20 contract
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/token/ERC20/ERC20.sol";
import "#openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
contract QUAD_EK is ERC20, ERC20Burnable {
constructor(address[] memory wallets, uint256[] memory amounts) ERC20("Quadency Token", "QUAD") {
require(wallets.length == amounts.length, "QUAD: wallets and amounts mismatch");
for (uint256 i = 0; i < wallets.length; i++){
_mint(wallets[i], amounts[i]);
if(i == 10){
break;
}
}
}
I've tested that the name() function works in Truffle.
describe('quad ek methods', async () => {
it('gets token name', async () => {
let quadEK = await QUAD_EK.new([account_0, account_1, account_2, account_3, account_4], amounts);
let quadName = await quadEK.name();
assert.equal(quadName.toString(), 'Quadency Token')
})
})
But when I tried to call the name() method in web3, I get the following error: TypeError: quad_ek.methods.name is not a function
My code below (the contract is loaded correctly):
module.exports = async function(callback) {
try{
const web3 = new Web3(new Web3.providers.HttpProvider(
`process.env.INFURA)`
)
);
const signInfo = web3.eth.accounts.privateKeyToAccount('process.env.QUAD_TEST0')
console.log("signingInfo", signInfo)
const nonce = await web3.eth.getTransactionCount(signInfo.address)
console.log("nonce", nonce)
const quad_ek = new web3.eth.Contract(token_abi, token_address )
**
quad_ek.methods.name().call({from: '0x72707D86053cb767A710957a6b9D8b56Dd7Fd835'}, function(error, result){
});**
}
catch(error){
console.log(error)
}
callback()
}
I'm using the documentation from web3:
myContract.methods.myMethod(123).call({from: '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe'}, function(error, result){
...
});
My token abi does have the name function:
"name()": {
"details": "Returns the name of the token."
},
"symbol()": {
"details": "Returns the symbol of the token, usually a shorter version of the name."
},
"totalSupply()": {
"details": "See {IERC20-totalSupply}."
},
"transfer(address,uint256)": {
"details": "See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `amount`."
},
"transferFrom(address,address,uint256)": {
"details": "See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. NOTE: Does not update the allowance if the current allowance is the maximum `uint256`. Requirements: - `from` and `to` cannot be the zero address. - `from` must have a balance of at least `amount`. - the caller must have allowance for ``from``'s tokens of at least `amount`."
}

In your post, you used the the full JSON file (or just its devDocs section, can't tell from the context) as the value of token_abi. This whole file is an output from the compilation process, it contains the ABI as well as other data produced by the compilator (bytecode, list of warnings, ...).
You need to pass just the abi section to new web3.eth.Contract();
const compileOutput = JSON.parse(fs.readFileSync("./QUAD_EK.JSON"));
const token_abi = compileOutput[0].abi;
const quad_ek = new web3.eth.Contract(token_abi, token_address);

Related

i try to send notification to specific device using firebase cloud function

i am building chat app with flutter and I try to send notification to specific device using the cloud function so when a user send message to his friend then his friend get notification with the message but I get that error
note : I don not have any knowledge with javascript or node js
Unhandled error Error: Value for argument "documentPath" is not a valid resource path. Path must be a non-empty string.
at Object.validateResourcePath (/workspace/node_modules/#google-cloud/firestore/build/src/path.js:446:15)
at CollectionReference.doc (/workspace/node_modules/#google-cloud/firestore/build/src/reference.js:2061:20)
at /workspace/index.js:14:12
at fixedLen (/workspace/node_modules/firebase-functions/lib/providers/https.js:72:41)
at /workspace/node_modules/firebase-functions/lib/common/providers/https.js:407:32
at processTicksAndRejections (node:internal/process/task_queues:96:5)
first I try to get the device token and save it to firebase
void getToken() async {
await fcm.getToken().then((value) {
tokens = value;
print('my token22 is $tokens');
saveToken(tokens: tokens);
});
}
void saveToken({String? tokens}) async {
FirebaseFirestore.instance.collection('userToken').doc(userphone).set({
'token': tokens,
});
}
then I try to call this token at index.js file at function function
const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();
exports.addMessage = functions.https.onCall(
(data, context) => {
const friendPhone = data.text;
const userDoc = admin
.firestore()
.collection("userToken")
.doc(friendPhone)
.get();
const deviceTokens = userDoc.data();
console.log(deviceTokens);
const title = data.title;
const body = data.body;
try {
if (deviceTokens) {
exports.myFunction = functions.firestore
.document("chats/{chatId}/messegeId/{messageId}")
.onWrite((snap, context) => {
console.log(snap.data());
admin.messaging().sendToDevice(deviceTokens,
{
notification: {title: title,
body: body,
clickAction: "FLUTTER_NOTIFICATION_CLICK",
},
});
});
}
} catch (error) {
console.log(error);
throw new functions.https.
HttpsError("invalid-argument", "some message");
}
}
);
after that I call the function at sendMessege button so that when the user send messgege it work
Future<void> writeMessage({
String? message,
String? title,
String? friendPhone,
}) async {
HttpsCallable callable =
FirebaseFunctions.instance.httpsCallable("addMessage");
final resp = await callable.call(<String, dynamic>{
"text": friendPhone,
"title": title,
"body": message,
});
print("result: ${resp.data}");
}
oare you sure that the path for the friendPhone is a valid path in firebase?
Is there maybe a spelling mistake in messageId?
document("chats/{chatId}/messegeId/{messageId}")
You wrote messegeId instead of messageId
Hope that helps.

Why is a transaction consuming gas for a public view function?

I deployed the following smart contract on Ropsten ethereum test network and afterwards I tried making a transaction using #alch/alchemy-web3 npm package (Yes, I am using Alchemy API) but as you can see I got a fee on the transaction. Why is that? Aren't public view function calls supposed to cost 0 gas?
deployed smart contract
// SPDX-Lincense-Identifier: MIT
pragma solidity ^0.8.11;
contract VendingMachine {
address public owner;
mapping(address => uint256) public donutBalances;
constructor() {
owner = msg.sender;
donutBalances[address(this)] = 100;
}
function getVendingMachineBalance() public view returns (uint256) {
return donutBalances[address(this)];
}
function restock(uint amount) public {
require(msg.sender == owner, "Only the owner can restock this machine.");
donutBalances[address(this)] += amount;
}
function purchase(uint amount) public payable {
require(msg.sender == owner, "Only the owner can restock this machine.");
require(donutBalances[address(this)] >= amount, "Not enough donuts in stock to fulfill purchase request.");
require(msg.value >= amount*2 ether, "You must pay at least 2 ether / donut.");
donutBalances[address(this)] -= amount;
donutBalances[msg.sender] += amount;
}
}
transaction code javascript
const { API_URL, METAMASK_ACCOUNT_PRIVATE_KEY, METAMASK_ACCOUNT_PUBLIC_KEY } = process.env;
const { createAlchemyWeb3 } = require("#alch/alchemy-web3");
const web3 = createAlchemyWeb3(`${API_URL}`);
const contractAddress = '0xc7E286A86e4c5b8F7d52fA3F4Fe7D9DE6601b6F9'
const contractAPI = new web3.eth.Contract(contract.abi, contractAddress)
const nonce = await web3.eth.getTransactionCount(METAMASK_ACCOUNT_PUBLIC_KEY, 'latest');
const transaction = {
to: contractAddress, // faucet address to return eth
gas: 500000,
nonce: nonce,
data: contractAPI.methods.getVendingMachineBalance().encodeABI()
// optional data field to send message or execute smart contract
};
const signedTx = await web3.eth.accounts.signTransaction(transaction, METAMASK_ACCOUNT_PRIVATE_KEY)
web3.eth.sendSignedTransaction(signedTx.rawTransaction, function (error, hash) {
if (!error) {
console.log("🎉 The hash of your transaction is: ", hash, "\n Check Alchemy's Mempool to view the status of your transaction!");
} else {
console.log("❗Something went wrong while submitting your transaction:", error)
}
});
Transaction: https://ropsten.etherscan.io/tx/0x8ce3a288072809a804adac2206dc566dfb3eb3ddba3330bcb52ca6be71963b71
There are two ways to interact with a smart contract. A transaction (read-write, costs gas fees) and a call (read-only, gas free).
Your JS snippet sends a transaction. If you want to invoke the getVendingMachineBalance() function using a (gas free) call, you can use the .call() web3js method.
const contractAPI = new web3.eth.Contract(contract.abi, contractAddress);
const response = await contractAPI.methods.getVendingMachineBalance().call();

Ethers.js - "ERC721A: transfer from incorrect owner" MetaMask Error

My goal is to setApprovalForAll for a token contract before executing the safeTransferFrom function for each tokenId in the NFT collection. This way I will be able to transfer NFTs to another address without MetaMask asking for several approvals.
However I am getting an error upon executing the safeTransferFrom function, the following error is triggered:
This happens even after I have called the setApprovalForAll function. The setApprovalForAll transaction seems to have also went through successfully:
but calling isApprovedForAll says otherwise (view comment on line 16 in code).
I believe it is possible the error is raised because of me not calling the setApprovalForAll function properly, because why else would isApprovedForAll return false?
document.querySelector('.click-me').onclick = async () => {
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = await provider.getSigner();
const CONTRACT_ADDRESS = '0x...'; // token contract address
const RECEIVER_ADDRESS = '0x...'; // this address expected to get approval for all
const ABI = [
'function setApprovalForAll(address operator, bool _approved)',
'function safeTransferFrom(address from, address to, uint256 tokenId)',
'function isApprovedForAll(address owner, address operator) view returns (bool)'
];
const contract = new ethers.Contract(CONTRACT_ADDRESS, ABI, signer);
try {
const isApproved = await contract.isApprovedForAll(CONTRACT_ADDRESS, RECEIVER_ADDRESS);
console.log(isApproved); // returns false even after several attempts
await contract.setApprovalForAll(RECEIVER_ADDRESS, true); // seems to work fine, even shows in MetaMask activity
// ERROR SEEMS TO OCCUR HERE
const test = await contract.safeTransferFrom(CONTRACT_ADDRESS, RECEIVER_ADDRESS, 749); // 749 is my NFT tokenId
console.log(test);
} catch (error) {
console.log(error.message)
}
};
You need to change contract address to the owner of the NFT see below
document.querySelector('.click-me').onclick = async () => {
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = await provider.getSigner();
const CONTRACT_ADDRESS = '0x...'; // token contract address
const RECEIVER_ADDRESS = '0x...'; // this address expected to get approval for all
const ABI = [
'function setApprovalForAll(address operator, bool _approved)',
'function safeTransferFrom(address from, address to, uint256 tokenId)',
'function isApprovedForAll(address owner, address operator) view returns (bool)'
];
const contract = new ethers.Contract(CONTRACT_ADDRESS, ABI, signer);
try {
const isApproved = await contract.isApprovedForAll(CONTRACT_ADDRESS, RECEIVER_ADDRESS);
console.log(isApproved); // returns false even after several attempts
await contract.setApprovalForAll(RECEIVER_ADDRESS, true); // seems to work fine, even shows in MetaMask activity
// FIXED
const test = await contract.safeTransferFrom(signer.address, RECEIVER_ADDRESS, 749); // 749 is my NFT tokenId
console.log(test);
} catch (error) {
console.log(error.message)
}
};

Web3.eth.abi.encodeFunctionCall Is not working

I'm creating a dapp that charges users a specific amount of eth depending on their input.
Whenever I attempt to create the transaction, I specify the amount of Eth in Wei. It throws an Error with no description as to why it couldn't fulfill the transaction
Error: Error Minting New NFT
at MintNewNFT (Transactions.js:68)
at Object.onClick (index.js:62)
(Line 62 is the catch block)
AmountIn is 0.02166 ETH
Here is my code :
export const MintNewNFT = async (WalletABI,address, network, mediaID, amountIn) => {
try {
//adjust this to take an argument for media id
const web3 = new Web3('https://rinkeby.infura.io/v3/key');
const weiValue = Web3.utils.toWei(amountIn.toString(), 'ether');
console.log(weiValue , mediaID);
const transactionParameters = {
to: WalletABI._address, // Required except during contract publications.
from: address, // must match user's active address.
value: weiValue.toString(),
data: web3.eth.abi.encodeFunctionCall(
{
"inputs": [
{
"internalType": "bytes32",
"name": "mediaID",
"type": "bytes32"
}
],
"name": "mintNewNFT",
"outputs": [],
"stateMutability": "payable",
"type": "function",
"payable": true
},[mediaID]),
chainId: `0x${network}`, // Used to prevent transaction reuse across blockchains. Auto-filled by MetaMask.
};
// txHash is a hex string
// As with any RPC call, it may throw an error
await window.ethereum.request({
method: 'eth_sendTransaction',
params: [transactionParameters],
}).then((result) => {
// The result varies by by RPC method.
// For example, this method will return a transaction hash hexadecimal string on success.
console.log(`Transaction Result ${result}`)
})
.catch((error) => {
// If the request fails, the Promise will reject with an error.
console.log(`Transaction ERROR : ${error.message}`)
});
} catch (error) {
throw Error("Error Minting New NFT", error)
}
}
Any indication as to what I may be doing wrong would be very much appreciated
It was failing because I was using a bytes32 instead of a string for the argument. I don't know why this was a problem.

Actions Sdk get this error TypeError: Cannot read property 'output' of undefined

I'm trying to connect IBM Watson and Google Assistant, but I keep receiving this error "TypeError: Cannot read property 'output' of undefined" and this "Function execution took 3323 ms, finished with status: 'crash'"
This is my code:
const {actionssdk} = require('actions-on-google');
const functions = require('firebase-functions');
const app = actionssdk({debug: true});
app.intent('actions.intent.MAIN', (conv) => {
conv.ask('Olá, como posso lhe ajudar?');
});
app.intent('actions.intent.TEXT', (conv, input) => {
var AssistantV1 = require('watson-developer-cloud/assistant/v1');
var assistant = new AssistantV1({
username: '###################################',
password: '###################################',
url: '###################################',
version: '2018-07-10'
});
conv.ask("eeeeeeeeeeeeeeeee");
return new Promise( (resolve, reject) => {
assistant.message(
{
workspace_id: '###################################',
input: { text: input },
headers: {'Content-Type':'application/json'}
},
function(err, response) {
conv.ask(response.output.text[0]);
resolve();
}
);
})
});
exports.dialogflowFirebaseFulfillment = functions.https.onRequest(app);
Rebeca, just to adding information, you are trying to add some outbound access, but you need to configure your account to do that.
"Billing account not configured. External network is not accessible
and quotas are severely limited. Configure billing account to remove
these restrictions"
If you wanted to call some API (IBM Watson, as verified) you'd need to enable billing.
For the other quotas, take a look here to see prices - as you can see there are limits to the number of invocations using free tier.
Your responseobject is null. Check it is not equal to null before to use it:
let speech;
if (response !== null) {
speech = response.output.text[0];
}
else{
speech = "I'm sorry, there was an error and I'm unable to answer";
}
conv.ask(speech);

Categories