Solidity error 'Invalid number of parameters for "undefined" ' - javascript

I'm trying to follow along with one of the solidity tutorials on youtube. And I'm getting stuck at this particular moment.
This is a solidity code:
pragma solidity ^0.5.0;
import "./Token.sol";
contract EthSwap {
string public name = "EthSwap Instant Exchange";
Token public token;
constructor(Token _token) public {
token = _token;
}
}
Here is a deployment code:
const Token = artifacts.require("Token");
const EthSwap = artifacts.require("EthSwap");
module.exports = async function(deployer) {
// Deploy Token
await deployer.deploy(Token);
const token = await Token.deployed()
// Deploy EthSwap
await deployer.deploy(EthSwap, token.address);
const ethSwap = await EthSwap.deployed()
// Transfer all tokens to EthSwap (1 million)
await token.transfer(ethSwap.address, '1000000000000000000000000')
};
And this is a code for automated test:
const Token = artifacts.require("Token");
const EthSwap = artifacts.require("EthSwap");
require('chai')
.use(require('chai-as-promised'))
.should()
function tokens(n) {
return web3.utils.toWei(n, 'ether');
}
contract('EthSwap', (accounts) => {
let token, ethSwap
before(async () => {
token = await Token.new()
ethSwap = await EthSwap.new(token.address)
// Transfer all tokens to EthSwap (1 million)
await token.transfer(ethSwap.address, tokens('1000000'))
})
describe('Token deployment', async () => {
it('contract has a name', async () => {
let token = await Token.new()
const name = await token.name()
assert.equal(name, 'DApp Token')
})
})
describe('EthSwap deployment', async () => {
it('contract has a name', async () => {
let ethSwap = await EthSwap.new()
const name = await ethSwap.name()
assert.equal(name, 'EthSwap Instant Exchange')
})
it('contract has tokens', async () => {
let balance = await token.balanceOf(ethSwap.address)
assert.equal(balance.toString(), tokens('1000000'))
})
})
})
The test runed normally before I added this code to the solidity code:
constructor(Token _token) public {
token = _token;
}
Now I get the following in my terminal:
2 passing (559ms)
1 failing
Contract: EthSwap
EthSwap deployment
contract has a name:
Invalid number of parameters for "undefined". Got 0 expected 1!
Error
at PromiEvent (C:\Users\user\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\contract\lib\promievent.js:9:1)
at C:\Users\user\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\contract\lib\execute.js:223:1
at Function.new (C:\Users\user\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\contract\lib\contract\constructorMethods.js:57:1)
at _callee4$ (C:/Users/user/eth_swap/test/EthSwap.test.js:32:24)
at tryCatch (node_modules#babel\runtime\node_modules\regenerator-runtime\runtime.js:45:40)
at Generator.invoke [as _invoke] (node_modules#babel\runtime\node_modules\regenerator-runtime\runtime.js:271:22)
at Generator.prototype. [as next] (node_modules#babel\runtime\node_modules\regenerator-runtime\runtime.js:97:21)
at step (test\EthSwap.test.js:3:191)
at C:\Users\user\eth_swap\test\EthSwap.test.js:3:437
at new Promise ()
at Context. (test\EthSwap.test.js:3:99)
at processImmediate (node:internal/timers:466:21)
Can someone explane what might be the problem. It seems that I did everything exactly as done in the tutorial.

Your contract has constructor function set. constructor function means when you initalize an instance, you have to pass arguments that used in constructor(Token _token). this argument probably is the "address". So in your deployment function
await deployer.deploy(Token);
you have to pass the token as the second argument
await deployer.deploy(Token,tokenAddress);
if you needed more arguments, you would just pass them in order. first argument is the contract, then arguments in constructor, and the last argument is the options object if needed

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.

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)
}
};

How to properly transfer Solana SOL using web3js via Phantom

Am working with Solana Blockchain. Am trying to transfer Solana SOL via Phantom. To this effect I used the code below which was found on Stack Overflow: source link
I already have Phantom installed in Chrome. When I run the code, it displays error:
Uncaught (in promise) TypeError: Cannot read properties of null (reading 'toString')
I think its this line of code that is causing the error above
console.log("Public key of the emitter: ",provider.publicKey.toString());
Here is the Code
import * as web3 from '#solana/web3.js';
import * as splToken from '#solana/spl-token';
const getProvider = async () => {
if ("solana" in window) {
const provider = window.solana;
if (provider.isPhantom) {
console.log("Is Phantom installed? ", provider.isPhantom);
return provider;
}
} else {
window.open("https://www.phantom.app/", "_blank");
}
};
async function transferSOL() {
// Detecing and storing the phantom wallet of the user (creator in this case)
var provider = await getProvider();
console.log("Public key of the emitter: ",provider.publicKey.toString());
// Establishing connection
var connection = new web3.Connection(
web3.clusterApiUrl('devnet'),
);
// I have hardcoded my secondary wallet address here. You can take this address either from user input or your DB or wherever
var recieverWallet = new web3.PublicKey("CkiKLEa9eSEoG6CoTSuaahsF2WqNgArnvoCSbNZjJ7BQ");
// Airdrop some SOL to the sender's wallet, so that it can handle the txn fee
var airdropSignature = await connection.requestAirdrop(
provider.publicKey,
web3.LAMPORTS_PER_SOL,
);
// Confirming that the airdrop went through
await connection.confirmTransaction(airdropSignature);
console.log("Airdropped");
var transaction = new web3.Transaction().add(
web3.SystemProgram.transfer({
fromPubkey: provider.publicKey,
toPubkey: recieverWallet,
lamports: web3.LAMPORTS_PER_SOL //Investing 1 SOL. Remember 1 Lamport = 10^-9 SOL.
}),
);
// Setting the variables for the transaction
transaction.feePayer = await provider.publicKey;
let blockhashObj = await connection.getRecentBlockhash();
transaction.recentBlockhash = await blockhashObj.blockhash;
// Transaction constructor initialized successfully
if(transaction) {
console.log("Txn created successfully");
}
// Request creator to sign the transaction (allow the transaction)
let signed = await provider.signTransaction(transaction);
// The signature is generated
let signature = await connection.sendRawTransaction(signed.serialize());
// Confirm whether the transaction went through or not
await connection.confirmTransaction(signature);
//Signature chhap diya idhar
console.log("Signature: ", signature);
}
You need to connect to the wallet. That part is missing
const getProvider = async () => {
if ("solana" in window) {
// opens wallet to connect to
await window.solana.connect();
const provider = window.solana;
if (provider.isPhantom) {
console.log("Is Phantom installed? ", provider.isPhantom);
return provider;
}
} else {
window.open("https://www.phantom.app/", "_blank");
}
};
I'm not sure if this is the best solution going ahead, but yours is a problem of the persistence of the phantom wallet after the user signs in. You'll have to go for front-end heavy solution for this. One of which is:
Assuming you are using React, use context APIs to persist the data about the wallet. Here is a rough guideline on how to do that by creating a file under the context folder in your project root:
import React, { createContext, useState} from "react";
export const WalletDataContext=createContext();
export const WalletDataContextProvider=(props)=>{
const [publicKey,setPublicKey]=useState(null);
const [wallet,setWallet]=useState(null);
return (
<WalletDataContext.Provider
value={{publicKey,setPublicKey,wallet,setWallet}}
>
{props.children}
</WalletDataContext.Provider>
)
}
Create a connectWallet function, something like this:
//import {WalletDataContext}
//import other stuff:
const {setPublicKey,setWallet}=useContext(WalletDataContext)
const connectWallet = async() {
const provider = await getProvider();
if(provider) {
await provider.connect();
let publicKey = "";
provider.on("connect", async () => {
setWallet(provider);
publicKey = provider.pubicKey.toString();
setPublicKey(publicKey);
/*
// more things that you would like to do here
*/
});
}
}
Make the following changes in your transferSOL function:
async function transferSOL() {
//Changes are only here, in the beginning
const phantomProvider = wallet;
if(!phantomProvider){
//Urge the user to sign in(connect) again
}
const pubKey = await phantomProvider.publicKey;
console.log("Public Key: ", pubKey);
// Establishing connection
var connection = new web3.Connection(
web3.clusterApiUrl('devnet'),
);
// I have hardcoded my secondary wallet address here. You can take this address either from user input or your DB or wherever
var recieverWallet = new web3.PublicKey("CkiKLEa9eSEoG6CoTSuaahsF2WqNgArnvoCSbNZjJ7BQ");
// Airdrop some SOL to the sender's wallet, so that it can handle the txn fee
var airdropSignature = await connection.requestAirdrop(
provider.publicKey,
web3.LAMPORTS_PER_SOL,
);
// Confirming that the airdrop went through
await connection.confirmTransaction(airdropSignature);
console.log("Airdropped");
var transaction = new web3.Transaction().add(
web3.SystemProgram.transfer({
fromPubkey: provider.publicKey,
toPubkey: recieverWallet,
lamports: web3.LAMPORTS_PER_SOL //Investing 1 SOL. Remember 1 Lamport = 10^-9 SOL.
}),
);
// Setting the variables for the transaction
transaction.feePayer = await provider.publicKey;
let blockhashObj = await connection.getRecentBlockhash();
transaction.recentBlockhash = await blockhashObj.blockhash;
// Transaction constructor initialized successfully
if(transaction) {
console.log("Txn created successfully");
}
// Request creator to sign the transaction (allow the transaction)
let signed = await provider.signTransaction(transaction);
// The signature is generated
let signature = await connection.sendRawTransaction(signed.serialize());
// Confirm whether the transaction went through or not
await connection.confirmTransaction(signature);
//Signature or the txn hash
console.log("Signature: ", signature);
}
I think you problem is here:
// Request creator to sign the transaction (allow the transaction)
let signed = await provider.signTransaction(transaction);
// The signature is generated
let signature = await connection.sendRawTransaction(signed.serialize());
// Confirm whether the transaction went through or not
await connection.confirmTransaction(signature);
You sign using provider, but you send using connection, try change this:
const { signature } = await provider?.signAndSendTransaction(
transaction
);
await connection.getSignatureStatus(signature);
return signature;

TypeError: ping is not a function

Im trying to make a discord bot that shows my minecraft server stats and stuff. It is almost done but when i do the command it comes up with this in the terminal: TypeError: ping is not a function. Here is my code:
const {Client, RichEmbed } = require('discord.js')
const bot = new Client()
const ping = require('minecraft-server-util')
const token = 'not gunna tell u my token'
const ip = 'or ip'
const PREFIX = '!'
bot.on('ready', () =>{
console.log('Bot has come online.')
})
bot.on('message', message =>{
let args = message.content.substring(PREFIX.length).split(' ')
switch(args[0]){
case 'mc':
ping(ip, parseInt(25565), (error, reponse) =>{
if(error) throw error
const Embed = new RichEmbed()
.setTitle('Server Status')
.addField('Server IP', reponse.host)
.addField('Server Version', reponse.version)
.addField('Online Players', reponse.onlinePlayers)
.addField('Max Players', reponse.maxPlayers)
message.channel.send(Embed)
})
break
}
})
bot.login(token)
As the docs say, ping is a property of that module's exports: it's not the whole export:
const util = require('minecraft-server-util');
util.ping('play.hypixel.net', { port: 25565 })
For your code, either destructure out the ping property on import:
const { ping } = require('minecraft-server-util')
Or give it some other name, then call .ping on the imported object:
const util = require('minecraft-server-util');
// ...
util.ping(ip, /* etc */
Also, if you want the port to be the default 25565, there's no need to pass it at all. The module also returns a Promise, which you should use instead of the callback form:
ping(ip)
.then((response) => {
// handle response
})
.catch((error) => {
// handle errors
});

Error creating a payment intent for Stripe with Firebase in NodeJS

I'm attempting to create a Stripe payment intent in NodeJS with Firebase. Server function receives JSON from my iOS app, retrieves the product correctly and gets the product's price (which is confirmed by the correct values in console), but at the very last step it doesn't pass the price value correctly.
Here's the error I receive in my Firebase console:
Error: Invalid integer: {:domain=>{:domain=>"", :_eventsCount=>"1"}}
at Function.generate (/srv/node_modules/stripe/lib/Error.js:38:16)
at IncomingMessage.res.once (/srv/node_modules/stripe/lib/StripeResource.js:175:33)
at Object.onceWrapper (events.js:313:30)
at emitNone (events.js:111:20)
at IncomingMessage.emit (events.js:208:7)
at endReadableNT (_stream_readable.js:1064:12)
at _combinedTickCallback (internal/process/next_tick.js:139:11)
at process._tickDomainCallback (internal/process/next_tick.js:219:9)
And here's the code:
// New Stripe Payment Intent
const newPaymentIntent = express();
newPaymentIntent.use(bodyParser.urlencoded({ extended: true }));
newPaymentIntent.post('/', (req, res) => { createPaymentIntent(req, res); });
function paymentIntent(req, res) { }
exports.paymentIntent = functions.https.onRequest(newPaymentIntent);
const calculateOrderAmount = items => {
let price = admin.database().ref('/productAds').orderByChild('code').equalTo(items['code']).once('value').then((snapshot) => {
var productPrice = 99;
snapshot.forEach((childSnapshot) => {
var childData = childSnapshot.val();
productPrice += childData.price;
console.log(childData.price);
});
console.log(productPrice);
return productPrice;
});
return price;
};
// Create Stripe Customer
async function createPaymentIntent(req, res) {
const { items, currency } = req.body;
const paymentIntent = await stripe.paymentIntents.create({
amount: calculateOrderAmount(items),
currency: 'aud',
});
const clientSecret = paymentIntent.client_secret
// Send publishable key and PaymentIntent details to client
res.send({
publishableKey: 'pk_test_ikLVo1vJSDi89gcfwMiBTDDw',
clientSecret: clientSecret
});
}
Any suggestions on what I am doing wrong?
Your function calculateOrderAmount doesn't return a number. It returns a promise that will resolve with the value returned by the function you passed to then.
You should use another then to wait for the final value, and only then invoke the stripe API. Or use async. (If you have the capability of using async, you should probably also use it in your calculateOrderAmount function instead of using then, as it will be easier to read and reason about.)
So Doug was correct. I edited the code to include async functions and it works flawlessly now. Here's what the final code looks like:
// Retrieve product code from Firebase
async function getDataFromFirebase(items) {
const objects = await admin.database().ref('/productAds').orderByChild('code').equalTo(items['code'])
const data = await objects.once('value');
return data;
}
async function getPrice(items) {
console.log('Executing getPrice method.');
var resultPrice = 0;
// we wait for the axios.get Promise to be resolved
const objects = await getDataFromFirebase(items);
objects.forEach((childSnapshot) => {
var childData = childSnapshot.val();
resultPrice += childData.price;
});
console.log('Price is: ' + resultPrice);
// we then return the data, just like we did in the callback-based version!
return resultPrice;
}
// Create Stripe Customer
async function createPaymentIntent(req, res) {
const { items, currency } = req.body;
const paymentIntent = await stripe.paymentIntents.create({
amount: await getPrice(items),
currency: 'aud',
});
const clientSecret = paymentIntent.client_secret
// Send publishable key and PaymentIntent details to client
res.send({
publishableKey: 'pk_test_ikLVo1vJSDi89gcfwMiBTDDw',
clientSecret: clientSecret
});
}

Categories