Hardhat, ether.js. TypeError: deployer.sendTransaction is not a function error. Trying to execute exactInput UniswapV3 function - ethereum

Im trying to execute a swap to buy Uni using UniswapV3 interface.
It sends me this error related to the sendTransaction() function and I dont understand why as a lot of examples that I have seen use it this way.
Im using hardhat as you can see and calling the getToken() from another script and deploying on goerli network. Function to check UNI wallet balnceOf() at the end works fine.
Also what advice would you recommend me to improve my code?
This is the code:
const { ethers, getNamedAccounts, network } = require("hardhat")
const {abi: V3SwapRouterABI} = require('#uniswap/v3-periphery/artifacts/contracts/interfaces/ISwapRouter.sol/ISwapRouter.json')
const FEE_SIZE = 3
function encodePath(path, fees) {
if (path.length != fees.length + 1) {
throw new Error('path/fee lengths do not match')
}
let encoded = '0x'
for (let i = 0; i < fees.length; i++) {
// 20 byte encoding of the address
encoded += path[i].slice(2)
// 3 byte encoding of the fee
encoded += fees[i].toString(16).padStart(2 * FEE_SIZE, '0')
}
// encode the final token
encoded += path[path.length - 1].slice(2)
return encoded.toLowerCase()
}
async function getToken() {
// const signer = provider.getSigner()
const deadline = Math.floor(Date.now()/1000) + (60*10)
const wethToken= "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
const Uni= "0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984"
const UniswapRouter="0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45"
const path = encodePath([wethToken, Uni], [3000])
console.log(path)
const { deployer } = await getNamedAccounts()
const UniV3Contract = await ethers.getContractAt(
V3SwapRouterABI,
UniswapRouter,
deployer
)
const params = {
path: path,
recipient:deployer,
deadline: deadline,
amountIn: ethers.utils.parseEther('0.01'),
amountOutMinimum: 0
}
const encodedData = UniV3Contract.interface.encodeFunctionData("exactInput", [params])
const txArg = {
to: UniswapRouter,
from: deployer,
data: encodedData,
gasLimit: ethers.utils.hexlify(1000000)
}
const tx = await deployer.sendTransaction(txArg)
console.log('tx: ', tx)
const IUni = await ethers.getContractAt(
"IERC20",
Uni,
deployer
)
const UniBlance = await IUni.balanceOf(deployer)
console.log(`Got ${UniBlance.toString()} UNI`)
}
module.exports = { getToken }
Without using the hardhat enviorment:
const {abi: V3SwapRouterABI} = require('#uniswap/v3-periphery/artifacts/contracts/interfaces/ISwapRouter.sol/ISwapRouter.json')
const { ethers } = require("ethers")
require("dotenv").config()
const INFURA_URL_TESTNET = process.env.INFURA_URL_TESTNET
const PRIVATE_KEY = process.env.PRIVATE_KEY
const WALLET_ADDRESS = process.env.WALLET_ADDRESS
// now you can call sendTransaction
const wethToken= "0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6"
const Uni= "0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984"
const UniswapRouter="0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45"
const UniV3Contract = new ethers.Contract(
UniswapRouter,
V3SwapRouterABI
)
const provider = new ethers.providers.JsonRpcProvider(INFURA_URL_TESTNET)
const wallet = new ethers.Wallet(PRIVATE_KEY)
const signer = wallet.connect(provider)
const FEE_SIZE = 3
function encodePath(path, fees) {
if (path.length != fees.length + 1) {
throw new Error('path/fee lengths do not match')
}
let encoded = '0x'
for (let i = 0; i < fees.length; i++) {
// 20 byte encoding of the address
encoded += path[i].slice(2)
// 3 byte encoding of the fee
encoded += fees[i].toString(16).padStart(2 * FEE_SIZE, '0')
}
// encode the final token
encoded += path[path.length - 1].slice(2)
return encoded.toLowerCase()
}
async function getToken() {
const path = encodePath([wethToken, Uni], [3000])
const deadline = Math.floor(Date.now()/1000) + (60*10)
const params = {
path: path,
recipient: WALLET_ADDRESS,
deadline: deadline,
amountIn: ethers.utils.parseEther('0.01'),
amountOutMinimum: 0
}
const encodedData = UniV3Contract.interface.encodeFunctionData("exactInput", [params])
const txArg = {
to: UniswapRouter,
from: WALLET_ADDRESS,
data: encodedData,
gasLimit: ethers.utils.hexlify(1000000)
}
const tx = await signer.sendTransaction(txArg)
console.log('tx: ', tx)
const receipt = tx.wait()
console.log('receipt: ', receipt)
}
module.exports = { getToken }

I could not find documentation for getNamedAccounts but when I check the source code, I get this signature
getNamedAccounts: () => Promise<{
[name: string]: Address;
}>;
this just returns an array of account addresses and used in hardhat.config.js
namedAccounts: {
deployer: {
default: 0, // by default take the first account as deployer
1: 0,
},
},
to send the transaction programmatically:
const { ethers } = require("ethers");
const provider = new ethers.providers.JsonRpcProvider(INFURA_TEST_URL);
const wallet = new ethers.Wallet(WALLET_SECRET);
const signer = wallet.connect(provider);
// now you can call sendTransaction
const tx = await signer.sendTransaction(txArg);

Related

Unable to initialize OpenZeppelin Clone contract during Hardhat Test (Error: VM Exception)

I'm trying to create clones of my implementation contract (EIP-1167) using the OpenZeppelin Clones library, however I keep getting a VM Exception Error.
This is the 'Initialize' function of my Implementation contract:
contract Whoopy is Initializable, VRFConsumerBaseV2, KeeperCompatible {
function initialize(address _whoopyCreator) public initializer {
VRFConsumerBaseV2.initialise(vrfCoordinatorV2);
i_vrfCoordinator = VRFCoordinatorV2Interface(vrfCoordinatorV2);
s_raffleState = RaffleState.CLOSED;
s_lastTimeStamp = block.timestamp;
whoopyCreator = _whoopyCreator;
i_vrfCoordinator.addConsumer(subscriptionId, address(this));
emit NewConsumerAdded(address(this));
}
This is my CloneFactory:
pragma solidity ^0.8.8;
import "#openzeppelin/contracts/proxy/Clones.sol";
contract WhoopyFactory {
address public implementationContract;
address[] public allClones;
event NewClone(address indexed _instance);
mapping(address => address) public whoopyList;
constructor(address _implementation) {
implementationContract = _implementation;
}
function createClone(address _whoopyCreator) payable external returns (address instance) {
instance = Clones.clone(implementationContract);
(bool success, ) = instance.call{value: msg.value}(abi.encodeWithSignature("initialize(address)", _whoopyCreator));
require(success==true, "initialize did not return true");
allClones.push(instance);
whoopyList[_whoopyCreator] = instance;
emit NewClone(instance);
return instance;
}
This is the test I am running:
const { assert, expect } = require("chai")
const { ethers, upgrades } = require("hardhat")
const { networkConfig } = require("../../helper-hardhat-config")
const fs = require("fs")
const path = require("path")
const { web3, Contract } = require("web3")
const getGas = async (tx) => {
const receipt = await ethers.provider.getTransactionReceipt(tx.hash)
return receipt.gasUsed.toString()
}
let whoopy,
Whoopy,
WhoopyFactory,
wf,
whoopyStandaloneGas,
whoopyFactoryGas,
clonedContract,
accountConnectedClone,
wCreator,
wallet,
addr1,
addr2
describe("Whoopy + WhoopyFactory", function () {
it("Initialises contract correctly", async function () {
provider = ethers.provider
addr1 = new ethers.Wallet("0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", provider)
addr2 = new ethers.Wallet("0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d", provider)
Whoopy = await ethers.getContractFactory("Whoopy", addr1)
whoopy = await Whoopy.deploy()
await whoopy.deployed()
const dir = path.resolve(
__dirname,
"/Users/boss/hardhat-smartcontract-lottery/artifacts/contracts/Whoopy.sol/Whoopy.json"
)
const file = fs.readFileSync(dir, "utf8")
const json = JSON.parse(file)
const abi = json.abi
WhoopyFactory = await ethers.getContractFactory("WhoopyFactory", addr1)
wf = await WhoopyFactory.deploy(whoopy.address)
await wf.deployed()
wf.connect(addr2)
const tx = await wf.createClone("0x70997970C51812dc3A010C7d01b50e0d17dc79C8", {
value: ethers.utils.parseUnits("1", "ether"),
})
console.log(tx)
const txReceipt = await tx.wait(1)
console.log(txReceipt)
})
})
When I run this test, I get the following error:
Error: VM Exception while processing transaction: reverted with reason string 'initialize did not return true'
This exact same code works perfectly when I try it in Remix, so I assume the issue has something to do with Hardhat.
Does anyone have any idea where the issue is? I've been racking my head for days but can't seem to figure out. I'd be extremely grateful if someone can point me in the right direction.
Thanks!
NOTE: Here is my hardhat config (in case it makes a difference):
require("#nomiclabs/hardhat-waffle")
require("#nomiclabs/hardhat-etherscan")
require("hardhat-deploy")
require("solidity-coverage")
require("hardhat-gas-reporter")
require("hardhat-contract-sizer")
require("dotenv").config()
require("#nomiclabs/hardhat-ethers");
// require('#openzeppelin/contracts');
const RINKEBY_RPC_URL = process.env.RINKEBY_RPC_URL
const PRIVATE_KEY = process.env.PRIVATE_KEY
const COINMARKETCAP_API_KEY = process.env.COINMARKETCAP_API_KEY
const ETHERSCAN_API_KEY = process.env.ETHERSCAN_API_KEY
/** #type import('hardhat/config').HardhatUserConfig */
module.exports = {
defaultNetwork: "hardhat",
networks: {
hardhat: {
chainId: 31337,
blockConfirmations: 1
},
localhost: {
chainId: 31337,
},
rinkeby: {
chainId: 4,
blockConfirmations: 6,
url: RINKEBY_RPC_URL,
accounts: [PRIVATE_KEY]
}
},
solidity: "0.8.8",
gasReporter: {
enabled: true,
currency: "USD",
outputFile: "gas-report.txt",
noColors: true,
// coinmarketcap: process.env.COINMARKETCAP_API_KEY,
},
namedAccounts: {
deployer: {
default: 0,
},
player: {
default: 1,
}
},
mocha: {
timeout: 900000,
},
etherscan: {
apiKey: {
rinkeby: ETHERSCAN_API_KEY,
// kovan: ETHERSCAN_API_KEY,
// polygon: POLYGONSCAN_API_KEY,
},
},
};

How to convert type data buffer to image using typescript and react

I'm having problems showing an image brought from the database.
-> First I'll show you how this image is being stored:
Here I do the import and send it to the backend
import profile_default_image from "../../../other/imgs/profile_default_image.png";
resRegister = await register(user_name, user_email, user_password, profile_default_image);
profile_default_image generates a type string with value =/static/media/profile_default_image.a9136072d073801df253.png
This value is stored in the MYSQL database in a BLOB type field.
Below is the profileImage value of a row
-> Now I'll show you what's happening on the front
const [profileImage, setProfileImage] = useState("test");
useEffect(() => {
async function getUser() {
if (id) {
const res = await apiFindUserById(id);
const base64Flag = "data:image/jpeg;base64,";
const b64Image = await Buffer.from(res.data.profileImage.data).toString("base64");
setProfileImage(base64Flag + b64Image);
}
}
getUser();
}, []);
res.data returns the following:
Below I try to put the image on the screen
<div>
<img style={{ width: 200, height: 200, }}
src={profileImage}
alt="test"
/>
</div>
But the only result I have is this:
I gave a console.log in profileImage and it returned the value of: data:image/jpeg;base64,L3N0YXRpYy9tZWRpYS9wcm9maWxlX2RlZmF1bHRfaW1hZ2UuYTkxMzYwNzJkMDczODAxZGYyNTMucG5n, which basically a blank image.
I tried another way to do(found it here on stackoverflow)
const [profileImage, setProfileImage] = useState("test");
const arrayBufferToBase64 = (buffer: any) => {
let binary = "";
let bytes = new Uint8Array(buffer);
let len = bytes.byteLength;
for (let i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i]);
}
return window.btoa(binary);
};
useEffect(() => {
async function getUser() {
if (id) {
const res = await apiFindUserById(id);
const imageStr = await arrayBufferToBase64(res.data.profileImage.data);
const base64Flag = "data:image/jpeg;base64,";
setProfileImage(base64Flag + imageStr);
console.log(profileImage);
}
}
getUser();
}, []);
I got the same result.
The original image is a default user avatar.
It could be that the problem is even when I'm storing this image in the database, can anyone help me? I'm very lost.
Thank you very much!!!

Invalid Json Response when accessing third-party service with Wix Corvid

I am attempting to gather details about real estate properties through an external API. I've gone over their documentation relentlessly but can not figure out why I am receiving the following error:
invalid json response body at https://api.gateway.attomdata.com/propertyapi/v1.0.0/property/expandedprofile?address1=34%20Karen%20Court&address2=Bridgeport20%CT reason: Unexpected token < in JSON at position
For reference, I am posting my code. If anyone can provide any input or guidance I would greatly appreciate it!
Backend Code:
import { fetch } from 'wix-fetch';
import { wixData } from 'wix-data';
export function getDetails(address, citystatezip) {
const url = 'https://api.gateway.attomdata.com/propertyapi/v1.0.0/property/expandedprofile?address1=' + address + "&address2=" + citystatezip;
let headers = {
"apikey": "xxxxxxxx",
"accept": "application/json"
};
let options = {
headers: headers
}
console.log("Url: " + url);
return fetch(url, { method: 'get' })
.then(response => {
return response.json();
})
.then((data) => {
console.log(data);
return data;
});
}
Page Code:
wixWindow.getCurrentGeolocation()
.then((obj) => {
let timestamp = obj.timestamp; // 1495027186984
let latitude = obj.coords.latitude; // 32.0971036
let longitude = obj.coords.longitude; // 34.774391099999995
let altitude = obj.coords.altitude; // null
let accuracy = obj.coords.accuracy; // 29
let altAccuracy = obj.coords.altitudeAccuracy; // null
let heading = obj.coords.heading; // null
let speed = obj.coords.speed;
console.log(obj)
reverse(latitude, longitude)
.then(geocode => {
console.log(geocode)
let id = geocode.results[0].place_id;
details(id)
.then(detailed => {
console.log(detailed)
$w("#input12").value = geocode.results[0].address_components[0].long_name + " " + geocode.results[0].address_components[1].long_name;
$w("#input10").value = geocode.results[0].address_components[3].long_name;
$w("#input11").value = geocode.results[0].address_components[5].long_name;
$w("#text37").text = geocode.results[0].formatted_address;
$w("#googleMaps2").location = {
"latitude": latitude,
"longitude": longitude,
"description": geocode.results[0].formatted_address
};
let address = geocode.results[0].address_components[0].long_name + " " + geocode.results[0].address_components[1].long_name;
let city = geocode.results[0].address_components[3].long_name;
let state = geocode.results[0].address_components[5].short_name;
let citystate = city +"%2C" + "%20" + state;
console.log(citystate)
const uri = address;
const encoded = encodeURI(uri);
console.log(encoded);
getDetails(encoded, citystate)
.then(got => {
console.log(got)
})
});
});
Thank you in advance for any input or guidance you can offer. I have spent hours trying to figure this out to no avail.
Stay safe and stay well 😊

Autodesk.DesignAutomation returning Unexpected token S in JSON at position 0 when calling the workitem api

I am facing a new issue with a fetch
handleSendToForge(e) {
e.preventDefault();
let formData = new FormData();
formData.append('data', JSON.stringify({
Width: this.state.Width,
Length: this.state.Length,
Depth: this.state.Depth,
Thickness: this.state.Thickness,
BottomThickness: this.state.BottomThickness,
rebarSpacing: this.state.rebarSpacing,
outputrvt: this.state.outputrvt,
bucketId: this.state.bucketId,
activityId: 'RVTDrainageWebappActivity',
objectId: 'template.rvt'
}));
this.setState({
form: formData
})
fetch('designautomation', {
method: 'POST',
body: formData,
//headers: {
// //'Content-Type': 'application/json'
// 'Content-Type': 'application/x-www-form-urlencoded',
//},
})
.then(response => response.json())
.then(data => { console.log(data) })
.catch(error => console.log(error));
}
and the code for the controller is pretty standard and is slightly modified from one of the forge examples
[HttpPost]
[Route("designautomation")]
public async Task<IActionResult> Test([FromForm] StartWorkitemInput input)
{
JObject workItemData = JObject.Parse(input.data);
double Width = workItemData["Width"].Value<double>();
double Length = workItemData["Length"].Value<double>();
double Depth = workItemData["Depth"].Value<double>();
double Thickness = workItemData["Thickness"].Value<double>();
double BottomThickness = workItemData["BottomThickness"].Value<double>();
double rebarSpacing = workItemData["rebarSpacing"].Value<double>();
string outputrvt = workItemData["outputrvt"].Value<string>();
string activityId = workItemData["activityId"].Value<string>();
string bucketId = workItemData["bucketId"].Value<string>();
string objectId = workItemData["objectId"].Value<string>();
// basic input validation
string activityName = string.Format("{0}.{1}", NickName, activityId);
string bucketKey = bucketId;
string inputFileNameOSS = objectId;
// OAuth token
dynamic oauth = await OAuthController.GetInternalAsync();
// prepare workitem arguments
// 1. input file
dynamic inputJson = new JObject();
inputJson.Width = Width;
inputJson.Length = Length;
inputJson.Depth = Depth;
inputJson.Thickness = Thickness;
inputJson.BottomThickness = BottomThickness;
inputJson.rebarSpacing = rebarSpacing;
inputJson.outputrvt = outputrvt;
XrefTreeArgument inputFileArgument = new XrefTreeArgument()
{
Url = string.Format("https://developer.api.autodesk.com/oss/v2/buckets/aecom-bucket-demo-library/objects/{0}", objectId),
Headers = new Dictionary<string, string>()
{
{ "Authorization", "Bearer " + oauth.access_token }
}
};
// 2. input json
XrefTreeArgument inputJsonArgument = new XrefTreeArgument()
{
Headers = new Dictionary<string, string>()
{
{"Authorization", "Bearer " + oauth.access_token }
},
Url = "data:application/json, " + ((JObject)inputJson).ToString(Formatting.None).Replace("\"", "'")
};
// 3. output file
string outputFileNameOSS = outputrvt;
XrefTreeArgument outputFileArgument = new XrefTreeArgument()
{
Url = string.Format("https://developer.api.autodesk.com/oss/v2/buckets/{0}/objects/{1}", bucketKey, outputFileNameOSS),
Verb = Verb.Put,
Headers = new Dictionary<string, string>()
{
{"Authorization", "Bearer " + oauth.access_token }
}
};
// prepare & submit workitem
// the callback contains the connectionId (used to identify the client) and the outputFileName of this workitem
//string callbackUrl = string.Format("{0}/api/forge/callback/designautomation?id={1}&bucketKey={2}&outputFileName={3}", OAuthController.FORGE_WEBHOOK_URL, browerConnectionId, bucketKey, outputFileNameOSS);
WorkItem workItemSpec = new WorkItem()
{
ActivityId = activityName,
Arguments = new Dictionary<string, IArgument>()
{
{ "rvtFile", inputFileArgument },
{ "jsonFile", inputJsonArgument },
{ "result", outputFileArgument }
///{ "onComplete", new XrefTreeArgument { Verb = Verb.Post, Url = callbackUrl } }
}
};
DesignAutomationClient client = new DesignAutomationClient();
client.Service.Client.BaseAddress = new Uri(#"http://localhost:3000");
WorkItemStatus workItemStatus = await client.CreateWorkItemAsync(workItemSpec);
return Ok();
}
Any idea why is giving me this error? I have tested the api using postman and it works fine but when I try to call that from a button I keep receive this error. Starting the debug it seems that the url is written correctly. Maybe it is a very simple thing that i am missing.
Cheers!
OK solved...
I was missing to add the service in the Startup and also the Forge connection information (clientid, clientsecret) in the appsettings.json
Now I need to test the AWS deployment and I guess I am done!

Why isn't my function returning the proper JSON data and how can I access it?

I'm running services to retrieve data from an API. Here is one of the services:
robotSummary(core_id, channel_name){
const params = new HttpParams()
var new_headers = {
'access-token': ' '
};
this.access_token = sessionStorage.getItem('access-token');
new_headers['access-token'] = this.access_token;
const myObject: any = {core_id : core_id, channel_name: channel_name};
const httpParams: HttpParamsOptions = { fromObject: myObject } as HttpParamsOptions;
const options = { params: new HttpParams(httpParams), headers: new_headers };
return this.http.get(this.baseURL + 'web_app/robot_summary/',options)
.subscribe(
res => console.log(res),
)
}
}
The data shows up properly on the console, but I still can't access the individual keys:
Here is how I call it:
ngOnInit(): void{
this.login.getData(this.username, this.password).subscribe((data) => {
this.robotSummaryData = this.getRobotSummary.robotSummary(this.core_id, this.channel_name);
console.log("robosummary"+ this.robotSummaryData)
});
}
When I call this function and assign it to a variable, it shows up on console as [object Object]. When I tried to use JSON.parse, it throws the error: type subscription is not assignable to parameter string. How can I access the data? I want to take the JSON object and save it as an Object with appropriate attributes. Thanks!
Do not subscribe inside your service, do subscribe in your component, change your service as follows,
robotSummary(core_id, channel_name){
const params = new HttpParams()
var new_headers = {
'access-token': ' '
};
this.access_token = sessionStorage.getItem('access-token');
new_headers['access-token'] = this.access_token; const myObject: any = { core_id: core_id, channel_name: channel_name };
const httpParams: HttpParamsOptions = { fromObject: myObject } as HttpParamsOptions;
const options = { params: new HttpParams(httpParams), headers: new_headers };
return this.http.get(this.baseURL + 'web_app/robot_summary/', options)
.map((response: Response) => response);
}
and then in your component,
ngOnInit(){
this.api..getRobotSummary.robotSummary(this.core_id, this.channel_name).subscribe((data) => {
this.data = data;
console.log(this.data);
});
}