Create autosigned transaction approval using moralis, ethers and metamask - javascript

I’m using metamask as web3provider. Have this code, that returns a token’s abi:
import abiErc20 from './abi-erc20.json'
import { ethers } from "ethers"
const abiObj = {
erc20abi: (tokenForAbi) => {
const provider = new ethers.providers.Web3Provider(window.ethereum)
const signer = provider.getSigner()
const contract = new ethers.Contract(tokenForAbi, abiErc20, signer)
return contract
},
methods: {
allowance: async (abi, wallet, router) => {
const res = await abi.allowance(wallet, router)
console.log('Allowance : ', res)
return res
},
balance: async (abi, wallet) => {
const res = await abi.balanceOf(wallet)
console.log('Balance : ', res)
return res
},
approve: async (abi, router, amount) => {
const res = await abi.approve(router, amount)
console.log('Approve : ', res)
return res
}
}
}
export default abiObj
And this part code, for call functions:
async function Approve() {
const abiFrom = abiObj.erc20abi('0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c')
console.log('AbiFrom: ', abiFrom)
setAbiFrom(abiFrom)
const allowanceChecked = await abiObj.methods.allowance(abiFrom, userAddress, exchangeAddresses.pancakeAddress)
const fromBalance = await abiObj.methods.balance(abiFrom, userAddress)
const fromApprove = await abiObj.methods.approve(abiFrom, '0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c', '100', userAddress)
}
Is there any way I can auto-sign the transaction approval, without the metamask pop-up?
Looked up docs, but not find anithing helpfull

No you cant. A transaction should be signed by user unless it is possible call approve inside your smart contract itself.

Related

I want to save a data from api to mongodb compass by mongose?

am trying to save a data from fetch api to my database using mongoose so
the data never come.
could anyone help? and thank you,
this is my code
`
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/Quran')
const SurahSchema = mongoose.Schema({
ayahs:[{
number:Number,
numberInSurah:Number,
text:String
}],
englishName:String,
englishNameTranslation:String,
name:String,
number:Number,
revelationType:String,
});
var surah = mongoose.model('Surah',SurahSchema)
`
`
const API = 'http://api.alquran.cloud/v1/quran/quran-uthmani'
async function getdata(){
const res = await fetch(API)
const data = await res.json()
for (let i = 0; i < data.data.surahs.length; i++) {
const Surah = new surah({
ayahs:[{
number:data.data.surahs[i]['ayahs'].number,
numberInSurah:data.data.surahs[i]['ayahs'].numberInSurah,
text:data.data.surahs[i]['ayahs'].text
}],
englishName:data.data.surahs[i]['englishName'],
englishNameTranslation:data.data.surahs[i]['englishNameTranslation'],
name:data.data.surahs[i]['name'],
number:data.data.surahs[i]['number'],
revelationType:data.data.surahs[i]['revelationType']
})
Surah.save(function (err) {
if (err) return handleError(err);
// saved!
});
}
}
getdata()
`
i tried to search about the problem in google and i did not find anything similar.
Instead of writing such a complicated for loop, you can just use the .insertMany() method on the model
const API = 'http://api.alquran.cloud/v1/quran/quran-uthmani'
async function getdata(){
const res = await fetch(API);
const data = await res.json();
try{
const inserted = await surah.insertMany(data.data.surahs);
}catch(e){
console.log("Some error");
console.log(e);
}
}
getdata()
the following is a complete working snippet
import mongoose from 'mongoose';
import fetch from 'node-fetch';
mongoose.connect('mongodb://localhost:27017/Quran');
const SurahSchema = mongoose.Schema({
ayahs: [
{
number: Number,
numberInSurah: Number,
text: String,
},
],
englishName: String,
englishNameTranslation: String,
name: String,
number: Number,
revelationType: String,
});
const surah = mongoose.model('Surah', SurahSchema);
const API = 'http://api.alquran.cloud/v1/quran/quran-uthmani';
async function getdata() {
const res = await fetch(API);
const data = await res.json();
try {
const inserted = await surah.insertMany(data.data.surahs);
console.log(inserted);
process.exit(0);
} catch (e) {
console.log('Some error');
console.log(e);
process.exit(0);
}
}
getdata();
this inserted 114 documents
PS: you just need to install node-fetch and mongoose

How to mock a curried function in jest?

I keep running into an issue where one of my curried functions is not a function when mocked out according to jest. I made a set of util httpRequest functions in a file called httpRequest.js that looks like this:
const httpRequest = (method) => {
return (headers) => {
return (data) => {
return async (url) => {
try {
const result = await axios({ method, url, data, headers });
const { data: axiosResult } = result;
return axiosResult;
} catch (err) {
console.log(`${method}Data: `, err);
throw err;
}
};
};
};
};
const getData = httpRequest('get')()();
const postData = httpRequest('post')();
const putData = httpRequest('put')();
const patchData = httpRequest('patch')();
const deleteData = httpRequest('delete')()();
const preBuiltGetRequest = httpRequest('get');
const preBuiltPostRequest = httpRequest('post');
const preBuiltPutRequest = httpRequest('put');
const preBuiltPatchRequest = httpRequest('patch');
const preBuiltDeleteRequest = httpRequest('delete');
module.exports = {
httpRequest,
getData,
postData,
putData,
patchData,
deleteData,
preBuiltGetRequest,
preBuiltPostRequest,
preBuiltPutRequest,
preBuiltPatchRequest,
preBuiltDeleteRequest,
};
When I mock out this file in a test and then use a function such as preBuiltGetRequest I get an error on jest saying TypeError: preBuiltGetRequest(...) is not a function. Here is an example of implementation of this.
Here is the function in my codebase I am testing:
queryUser: async (accessToken, email) => {
const query = `
{
getUsersByCriteria(criteria: Email, values: "${email}") {
id
groups {
id
name
entitlements {
id
code
}
members {
total
}
}
}
}
`;
const newUrl = new URL(`${BaseUrl}/v3/graphql`);
newUrl.searchParams.append('query', papiQuery);
console.log('From the Api ', preBuiltGetRequest);
const getAuthenticatedData = preBuiltGetRequest({
Authorization: `Bearer ${accessToken}`,
})();
const response = await getAuthenticatedData(newUrl.toString());
const graphQlResult = response.data?.getUsersByCriteria;
if (!graphQlResult || graphQlResult.length === 0) {
throw new Error(`Could not find user with email=${email}`);
}
return graphQlResult[0];
},
When I then run the test code mocking out preBuiltGetRequest using this code:
jest.mock('/opt/httpRequest');
const { preBuiltGetRequest } = require('/opt/httpRequest');
I receive this error:
The preBuiltGetRequest function has a signature that can be typed as
declare const prebuiltGetRequest: (header: object) => (data: object) => (url: String) => Promise<never>;
You need to mock it accordingly,
jest.mock('/opt/httpRequest');
const { preBuiltGetRequest } = require('/opt/httpRequest');
const mockSig = jest.fn().mockReturnValue(
jest.fn().mockResolvedValueOnce(error)
)
preBuiltGetRequest.mockReturnValue(mockSig)

I am making a project to add users in MongoDB but I am getting ERR_HTTP_HEADERS_SENT

import axios from 'axios';
// const usersUrl = 'http://localhost:3003/users';
const usersUrl = 'http://localhost:8020/users';
export const getUsers = async (id) => {
id = id || '';
return await axios.get(`${usersUrl}/${id}`);
}
export const addUser = async (user) => {
return await axios.post(`${usersUrl}/add`, user);
}
export const deleteUser = async (id) => {
return await axios.delete(`${usersUrl}/${id}`);
}
export const editUser = async (id, user) => {
return await axios.put(`${usersUrl}/${id}`, user)
}
This my client code when I try to add user it adds the user and details in back end in mongo db but cant view it in the front end when I click on the specific user.
import React, { useState, useEffect } from "react";
import { Link, useParams } from "react-router-dom";
import axios from "axios";
const usersUrl = 'http://localhost:8020/users';
const View = () => {
const [user, setUser] = useState({
projectname: '',
projecttype: '',
numberofissuesreported: '',
retestlead: '',
progress: '',
startdate: '',
enddate: '',
});
const { id } = useParams();
useEffect(() => {
loadUser();
//getUsers();
}, []);
const loadUser = async () => {
const res = await axios.get(`http://localhost:8020/users/add`);
setUser(res.data);
};
And this is my view.jsx file.
As the error mentions clearly, if you use response.send, it sends the data to the client. You cannot modify the states once they are sent.
Corrected Code:
export const addUser = async (request, response) => {
// retreive the info of user from frontend
const user = request.body;
// Removed the line
const newUser = new User(user);
try{
await newUser.save();
response.status(201).json(newUser);
} catch (error){
return response.status(404).json({ message: error.message});
}
}
Tip: If you are debugging, just use console.log instead of response.send and see those values on the terminal.
Example:
export const addUser = async (request, response) => {
// retreive the info of user from frontend
const user = request.body;
console.log("Executing..");
console.log(user);
const newUser = new User(user);
try{
await newUser.save();
response.status(201).json(newUser);
} catch (error){
return response.status(404).json({ message: error.message});
}
}

Getting an ENS error when interacting with a Smart Contract using ethers library

I everyone, I'm trying to call a function called 'safeMint' on an ERC721 contract deployed on Rinkeby testnet but I'm getting this error:
Error: resolver or addr is not configured for ENS name (argument="name", value="", code=INVALID_ARGUMENT, version=contracts/5.5.0)
This is the code I'm using to call the function
const mintNFT = async () => {
const {ethereum} = window;
if(isMetaMaskInstalled) {
try {
const abi = require('../contracts/Animals.json').abi;
console.log(abi);
const accounts = await ethereum.request({ method: 'eth_accounts' });
setAccount(accounts[0]);
const web3Provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = web3Provider.getSigner();
const contractWrite = new ethers.Contract('0x53Ea14980c8326E93a9F72889171c1e03d4aD6Ce', abi, signer);
let trx = await contractWrite.safeMint(account, props.cidOfJsonInIpfs);
console.log(trx);
} catch(err) {
console.log(err);
}
}
}
I've tried to print the parameters passed but they seem to be right, what am I doing wrong?
I solved it with the following code
const mintNFT = async () => {
const {ethereum} = window;
if(isMetaMaskInstalled) {
try {
const abi = require('../contracts/Animals.json').abi;
console.log(abi);
const accounts = await ethereum.request({ method: 'eth_accounts' });
const web3Provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = web3Provider.getSigner(accounts[0]);
console.log(signer._address)
const contractWrite = new ethers.Contract('0x53Ea14980c8326E93a9F72889171c1e03d4aD6Ce', abi, signer);
let trx = await contractWrite.safeMint(accounts[0], `https://gateway.pinata.cloud/ipfs/${props.cidOfFile}`);
let receipt = await trx.wait();
console.log(receipt);
} catch(err) {
console.log(err);
}
}
What I was missing: I was using setState function to set the 'account' state variable with the first account of metamask, instead, I started using account[0] directly and it worked!
I will accept this as solution in 2 days

Firestore cloud function to recursively update subcollection/collectionGroup

I have this cloud function:
import pLimit from "p-limit";
const syncNotificationsAvatar = async (
userId: string,
change: Change<DocumentSnapshot>
) => {
if (!change.before.get("published") || !change.after.exists) {
return;
}
const before: Profile = change.before.data() as any;
const after: Profile = change.after.data() as any;
const keysToCompare: (keyof Profile)[] = ["avatar"];
if (
arraysEqual(
keysToCompare.map((k) => before[k]),
keysToCompare.map((k) => after[k])
)
) {
return;
}
const limit = pLimit(1000);
const input = [
limit(async () => {
const notifications = await admin
.firestore()
.collectionGroup("notifications")
.where("userId", "==", userId)
.limit(1000)
.get()
await Promise.all(
chunk(notifications.docs, 500).map(
async (docs: admin.firestore.QueryDocumentSnapshot[]) => {
const batch = admin.firestore().batch();
for (const doc of docs) {
batch.update(doc.ref, {
avatar: after.avatar
});
}
await batch.commit();
}
)
);
})
];
return await Promise.all(input);
};
How can I recursively update the notifications collection but first limit the query to 1.000 documents (until there are not more documents) and then batch.update them? I'm afraid this query will timeout since collection could grow big over time.
Posting a solution I worked out, not following the context of the question though but it can easily be combined. Hope it helps someone else.
import * as admin from "firebase-admin";
const onResults = async (
query: admin.firestore.Query,
action: (batch: number, docs: admin.firestore.QueryDocumentSnapshot[]) => Promise<void>
) => {
let batch = 0;
const recursion = async (start?: admin.firestore.DocumentSnapshot) => {
const { docs, empty } = await (start == null
? query.get()
: query.startAfter(start).get());
if (empty) {
return;
}
batch++;
await action(
batch,
docs.filter((d) => d.exists)
).catch((e) => console.error(e));
await recursion(docs[docs.length - 1]);
};
await recursion();
};
const getMessages = async () => {
const query = admin
.firestore()
.collection("messages")
.where("createdAt", ">", new Date("2020-05-04T00:00:00Z"))
.limit(200);
const messages: FirebaseFirestore.DocumentData[] = [];
await onResults(query, async (batch, docs) => {
console.log(`Getting Message: ${batch * 200}`);
docs.forEach((doc) => {
messages.push(doc.data());
});
});
return messages;
};

Categories