ethers.js call to contract transaction fails - ethereum

Newbie to ethereum development...
I am using the sample code to keep it as simple as possible.
Using ethers.js and HardHat running on my local network.
The read function works ie. const data = await contract.greet()
The writes do not.
This code does not work, it just silently fails:
async function setGreeting() {
if (!greeting) return
if (typeof window.ethereum !== 'undefined') {
try {
await requestAccount()
const provider = new ethers.providers.Web3Provider(window.ethereum)
const signer = provider.getSigner()
const contract = new ethers.Contract(
greeterAddress,
Greeter.abi,
signer,
)
console.log('contract address = ' + contract.address) // this displays correctly
const transaction = await contract.setGreeting(greeting)
console.log('transaction = ' + transaction) // never displays
await transaction.wait()
} catch (err) {
console.log(err)
}
}
}
No error is thrown.
This line seems to be causing the issue:
const transaction = await contract.setGreeting(greeting)
All I see when testing is what seems to be an exception but nothing logged.
No transaction displays in HardHat.
What am I missing? Should an exception not be thrown?
Thanks!

Related

Sample APIConsumer contract not receiving ChainlinkFulfilled event in Hardhat

I deployed the APIConsumer sample contract (https://docs.chain.link/docs/make-a-http-get-request/) from Remix on Kovan, funded it with LINK, and sent a requestVolumeData transaction from Remix. As can be seen on Etherscan, the ChainlinkFulfilled event was fired: https://kovan.etherscan.io/address/0xde79d39db6b5210f83acf57346d74e5c762ab895#events.
Then I attached to the very same contract in Hardhat using a Kovan fork (with the Alchemy API key), and it never receives the event. Here is my test script:
const { ethers } = require("hardhat");
describe("API", function() {
it("Should make request and get result", async function() {
const ERC20 = await ethers.getContractFactory("ERC20")
const link = await ERC20.attach("0xa36085F69e2889c224210F603D836748e7dC0088"); //Kovan
console.log("name=" + await link.name());
const APIConsumer = await ethers.getContractFactory("APIConsumer");
const apiConsumer = APIConsumer.attach("0xde79d39db6B5210F83acf57346d74E5C762AB895");
//Ensure contract has sufficient LINK
console.log("balanceOf=" + await link.balanceOf(apiConsumer.address));
//Make request
const transaction = await apiConsumer.requestVolumeData()
const tx_receipt = await transaction.wait()
const requestId = tx_receipt.events[0].topics[1]
console.log("requestId=%s", requestId)
//Optionally subscribe to events
// apiConsumer.on("ChainlinkFulfilled", id => {
// console.log("ChainlinkFulfilled: %s", id);
// })
//Wait 30 secs for oracle to callback
await new Promise(resolve => setTimeout(resolve, 30000))
//Now check the result
const result = await apiConsumer.volume()
console.log("API Consumer Volume: %s", result)
});
});
In hardhat.config.js, blockNumber is chosen to be just before the first ChainlinkRequested event, and we can see from the script output that the contract is funded with sufficient LINK.
require("#nomiclabs/hardhat-waffle");
/**
* #type import('hardhat/config').HardhatUserConfig
*/
module.exports = {
solidity: "0.8.7",
networks: {
hardhat: {
forking: {
url: "https://eth-kovan.alchemyapi.io/v2/<API Key>",
blockNumber: 31301193
}
}
},
};
Script output
API
name=ChainLink Token
balanceOf=1000000000000000000
requestId=0x352988e0ddfe5c4349711ed9787069b1ea55bae562f676a08f6103435a874514
API Consumer Volume: 0
Why doesn't ChainlinkFulfilled seem to get fired from the Hardhat test?
Welcome, Peter! There is no oracle listening on your forked network. To test oracles locally you should consider mocking the oracle (hardhat way).

Getting an error when using methods.myMethod.call() with web3js

I am getting an error trying to call an existing smart contract function using call().
The error is "Returned values aren't valid, did it run Out of Gas? You might also see this error if you are not using the correct ABI for the contract you are retrieving data from, requesting data from a block number that does not exist, or querying a node which is not fully synced." My code is below
let url = 'https://api.etherscan.io/api?module=contract&action=getabi&address=0x672C1f1C978b8FD1E9AE18e25D0E55176824989c&apikey=<api-key>';
request(url, (err, res, body) => {
if (err) {
console.log(err);
}
let data = JSON.parse(body);
let contract_abi = JSON.parse(data.result);
let contract_address = '0x672C1f1C978b8FD1E9AE18e25D0E55176824989c';
const contract = new web3.eth.Contract(contract_abi, contract_address);
contract.methods.totalSupply().call()
.then(result => {
console.log('result', result);
}).catch(err => {
console.log('error: ', err);
})
})
When I execute the same function using send() it works, however I need the return value of the function which is why I want to use call(). I am using ganache to set up a local test network which is working fine. Thanks!

connect dapp with walletconnect to trust wallet

I use this code to connect to trustwallet:
https://docs.walletconnect.org/quick-start/dapps/client
This is my code:
const Web3Modal = window.Web3Modal.default;
const WalletConnectProvider = window.WalletConnectProvider.default;
const Fortmatic = window.Fortmatic;
const evmChains = window.evmChains;
const WalletConnect = window.WalletConnect
cosnt QRCodeModal = window.QRCodeModal
const connector = new WalletConnect({
bridge: "https://bridge.walletconnect.org", // Required
qrcodeModal: QRCodeModal,
});
// Check if connection is already established
if (!connector.connected) {
// create new session
connector.createSession();
}
// Subscribe to connection events
connector.on("connect", (error, payload) => {
if (error) {
throw error;
}
// Get provided accounts and chainId
const { accounts, chainId } = payload.params[0];
});
But now I don't understand - I should see a popup window with qrcode how do I summon this window?

Why can't I patch, update, or delete an AppPackage that I created?

I am trying to change the required engine version of an AppPackage that I have posted using v2 of the Design Automation API.
I've tried using Postman and the Forge Node Client. I'm using the Forge documentation as a reference.
https://forge.autodesk.com/en/docs/design-automation/v2/reference/http/AppPackages(':id')-PATCH/
My credentials are correct and I have a valid token, but for some reason I keep getting a 404 Not Found status and an error that says "AppPackage with the name MyPlugin doesn't belong to you. You cannot operate on AppPackage you do not own." Also, I get the same message when I try to delete or update the AppPackage.
That's really weird because I definitely own this AppPackage. I uploaded it with these same credentials and I can view it by doing a GET request to view all of my AppPackages. Furthermore, the name of the AppPackage is correct and I specified the right scope (code:all) when I authenticated.
Why does Design Automation think this AppPackage doesn't belong to me and why can't I patch, update, or delete it?
UPDATE 3/28/2019: Setting the resource value still results in the same error
UPDATE 4/2/2019: Getting a fresh upload URL doesn't work either. I get an internal server error saying "Object reference not set to an instance of an object."
const ForgeSDK = require('forge-apis');
const oAuth2TwoLegged = new ForgeSDK.AuthClientTwoLegged(FORGE_CLIENT_ID, FORGE_CLIENT_SECRET, SCOPES);
const appPackageApi = new ForgeSDK.AppPackagesApi();
const getToken = () => {
return oAuth2TwoLegged.authenticate();
};
const getUploadURL = () => {
return appPackageApi.getUploadUrl(oAuth2TwoLegged, oAuth2TwoLegged.getCredentials());
};
const patchPackage = (id, url) => {
const appPack = {
Resource: url,
RequiredEngineVersion: APP_PACKAGE_REQUIRED_ENGINE
};
return appPackageApi.patchAppPackage(id, appPack, oAuth2TwoLegged, oAuth2TwoLegged.getCredentials());
};
(async () => {
try {
const token = await getToken();
const url = await getUploadURL();
const patchPackRes = await patchPackage(APP_PACKAGE_ID, url);
if (patchPackRes.statusCode == 201)
console.log('Patch package succeeded!');
else
console.log('Patch package failed!' + patchPackRes.statusCode);
} catch (ex) {
console.log('Exception :(');
console.log(ex);
}
})();
When calling PATCH the "Resource" property must be set. It can be set to the same URL as the one you receive from GET but it must be present and valid.
This should work:
const ForgeSDK = require('forge-apis');
const oAuth2TwoLegged = new ForgeSDK.AuthClientTwoLegged(FORGE_CLIENT_ID, FORGE_CLIENT_SECRET, SCOPES);
const appPackageApi = new ForgeSDK.AppPackagesApi();
const getToken = () => {
return oAuth2TwoLegged.authenticate();
};
const getUploadURL = async (id) => {
const app = await appPackageApi.getAppPackage(id, oAuth2TwoLegged, oAuth2TwoLegged.getCredentials());
return app.body.Resource;
};
const patchPackage = (id, url) => {
const appPack = {
Resource: url,
RequiredEngineVersion: APP_PACKAGE_REQUIRED_ENGINE
};
return appPackageApi.patchAppPackage(id, appPack, oAuth2TwoLegged, oAuth2TwoLegged.getCredentials());
};
(async () => {
try {
const token = await getToken();
const url = await getUploadURL(APP_PACKAGE_ID);
const patchPackRes = await patchPackage(APP_PACKAGE_ID, url);
if (patchPackRes.statusCode == 201)
console.log('Patch package succeeded!');
else
console.log('Patch package failed!' + patchPackRes.statusCode);
} catch (ex) {
console.log('Exception :(');
console.log(ex);
}
})();

Error when subscribing to ERC-20 (BAT, i.e. Basic Attention Token)

I'm trying to subscribe to BAT(Basic Attention Token) ERC-20 token "Transfer" event to detect any transaction made to my ethereum address using web3 in nodejs. I'm using parity (Parity/v1.10.6-stable-bc0d134-20180605/x86_64-linux-gnu/rustc1.26.1) node running on same local machine -
parity --jsonrpc-hosts all --jsonrpc-apis all --ws-apis all --ws-hosts all --ws-origins all --ws-interface all
Here is the code that I've used to subscribe -
const Web3 = require('web3');
const abi = require('human-standard-token-abi');
var contract = '0x0D8775F648430679A709E98d2b0Cb6250d2887EF'; //BAT contract address
var web3Socket = new Web3(new Web3.providers.WebsocketProvider('ws://localhost:8546'));
function tokenEventListener = (address) => {
let token = new web3Socket.eth.Contract(abi, address);
console.log(address);
let subscription = token.events.Transfer({
fromBlock: 0
})
.on('data', (event) => {
// do something
})
.on('error', console.error);
}
tokenEventListener(contract);
I get an error when I run the code -
Error: CONNECTION ERROR: Couldn't connect to node on WS
It means that your node is not set up properly. Change:
var web3Socket = new Web3(new Web3.providers.WebsocketProvider('ws://localhost:8546'));
to
var web3Socket = new Web3(new Web3.providers.WebsocketProvider('wss://mainnet.infura.io/ws'));
This will connect to the Infura node which doesn't require you to host one.