Retrieve contract information with Web3js - ethereum

I am not able to retrieve a contract balance from a smart contract using Web3JS. I do not get an error either.
I have tried calling several other functions in addition to balanceOf and all of the them return the following:
[Symbol(kWeak)]: WeakReference {}.
Here is the code I am using:
contract.methods.balanceOf(address).call((err, result) => {console.log(result)})
Promise {
<pending>,
domain:
Domain {
domain: null,
_events:
[Object: null prototype] {
removeListener: [Function: updateExceptionCapture],
newListener: [Function: updateExceptionCapture],
error: [Function: debugDomainError] },
_eventsCount: 3,
_maxListeners: undefined,
members: [],
[Symbol(kWeak)]: WeakReference {} } }
The expected result should be the balance of the account for the given address.

I know you find your answer but for how just search for this problem.
you just have to resolve your promise with .then our use async/await syntax to resolve it like below.
contract.methods.balanceOf(address).call().then((balance) => console.log(balance))
or
async function getBalnce(){
const contract = await new web3Instance.eth.Contract(contractABI,contractAddress);
const balance = await contract.methods.balanceOf(address).call();
return balance;
}

Related

How to use React Testing Library to test for appearance/disappearance of elements in Gutenberg editor using Puppeteer?

I have the following set up:
E2E Test Utils - standard WP Gutenberg e2e testing set that uses Jest and Puppeteer
testing-library/pptr-testing-library - All your favorite user-centric querying functions from #testing-library/react & #testing-library/library available from Puppeteer!
I'm having a problem testing for appearance and disappearance of elements in the GB editor. I'm now aware that extended assertions don't work with Puppeteer. I just can't figure out what to test for. When I run the test in an interactive mode, I can see that everything is going fine, but I don't get the correct result. The result of the query is just an empty object. Here's a snippet of my code:
import {
enablePageDialogAccept,
setBrowserViewport,
createNewPost,
openDocumentSettingsSidebar,
insertBlock,
loginUser,
} from '#wordpress/e2e-test-utils';
import '#testing-library/jest-dom/extend-expect';
import { getDocument, queries, waitFor } from 'pptr-testing-library';
import { clearPuppeteerBrowser } from '../../../lib/helpers/e2eHelpers';
const {
getByRole,
getByLabelText,
getByDisplayValue,
getByText,
queryByLabelText,
findByRole,
findByLabelText,
findByText,
findAllByText,
} = queries;
describe('CVGB Button block', () => {
// Initialize vars within suite's scope
let $document;
let $editorSettings;
let $editorContent;
// Enable page dialog before running any tests
beforeAll(async () => {
await clearPuppeteerBrowser();
await loginUser();
await enablePageDialogAccept();
});
// Wait for creating a new post before running each of the tests
beforeEach(async () => {
await createNewPost();
$document = await getDocument(page);
// we want to look for Sidebar region only
$editorSettings = await getByRole($document, 'region', { name: 'Editor settings' });
// the same for the editor content, so we don't get repeated components from all the document
$editorContent = await getByRole($document, 'region', { name: 'Editor content' });
});
it('should be able to unset a Link when URL is already set', async () => {
await insertBlock('CVGB Button');
await openDocumentSettingsSidebar();
const $linkButton = await findByRole($document, 'button', {
name: 'Link',
});
await $linkButton.click();
const $URLInput = await findByRole($document, 'combobox', {
name: 'URL',
});
await $URLInput.click();
await $URLInput.type('https://www.google.es');
await $URLInput.press('Enter');
await waitFor(() => {
expect(
findByLabelText($document, 'Currently selected', {
exact: false,
})
).toBeInTheDocument();
});
});
});
Here is the error I see:
The complete Node error message below the test reads:
(node:41767) UnhandledPromiseRejectionWarning: Error: Protocol error (Runtime.callFunctionOn): Target closed.
at /Users/my-user/gb-siteapp/public/wp-content/plugins/cv-wp-gb-lib-blocks/node_modules/puppeteer-core/lib/cjs/puppeteer/common/Connection.js:208:63
at new Promise (<anonymous>)
at CDPSession.send (/Users/my-user/gb-siteapp/public/wp-content/plugins/cv-wp-gb-lib-blocks/node_modules/puppeteer-core/lib/cjs/puppeteer/common/Connection.js:207:16)
at ExecutionContext._evaluateInternal (/Users/my-user/gb-siteapp/public/wp-content/plugins/cv-wp-gb-lib-blocks/node_modules/puppeteer-core/lib/cjs/puppeteer/common/ExecutionContext.js:200:50)
at ExecutionContext.evaluateHandle (/Users/my-user/gb-siteapp/public/wp-content/plugins/cv-wp-gb-lib-blocks/node_modules/puppeteer-core/lib/cjs/puppeteer/common/ExecutionContext.js:151:21)
at /Users/my-user/gb-siteapp/public/wp-content/plugins/cv-wp-gb-lib-blocks/node_modules/pptr-testing-library/lib/index.ts:101:8
at Generator.next (<anonymous>)
at /Users/my-user/gb-siteapp/public/wp-content/plugins/cv-wp-gb-lib-blocks/node_modules/pptr-testing-library/dist/index.js:8:71
at new Promise (<anonymous>)
at Object.<anonymous>.__awaiter (/Users/my-user/gb-siteapp/public/wp-content/plugins/cv-wp-gb-lib-blocks/node_modules/pptr-testing-library/dist/index.js:4:12)
(node:41767) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 908)
EDIT: In response to Caleb Eby's asnwer
I thought that's what the waitFor() is for… however if I add only the await findByLabelText(), I get an error:
SyntaxError: /Users/my-user/gb-siteapp/public/wp-content/plugins/cv-wp-gb-lib-blocks/blocks/button/test/buttonBlock.e2e.spec.js: Unexpected reserved word 'await'. (126:16)
If I change it to:
await waitFor(async () => {
expect(
await findByLabelText($document, 'Currently selected', {
exact: false,
})
).toBeInTheDocument();
});
It takes a very long time to run the test and ends in error:
expect(received).toBeInTheDocument()
received value must be an HTMLElement or an SVGElement.
Received has type: object
Received has value:
{
"_client": {
"_callbacks": [Map],
"_connection": [Connection],
"_sessionId": "9E13F5776A59D1DD6A177F48A9D1A543",
"_targetType": "page",
"emitter": [Object],
"eventsMap": [Map]
},
"_context": {
"_client": [CDPSession],
"_contextId": 17,
"_world": [DOMWorld]
},
"_disposed": false,
"_frameManager": {
"_client": [CDPSession],
"_contextIdToContext": [Map],
"_frames": [Map],
"_isolatedWorlds": [Set],
"_mainFrame": [Frame],
"_networkManager": [NetworkManager],
"_page": [Page],
"_timeoutSettings": [TimeoutSettings],
"emitter": [Object],
"eventsMap": [Map]
},
"_page": {
"_accessibility": [Accessibility],
"_client": [CDPSession],
"_closed": false,
"_coverage": [Coverage],
"_emulationManager": [EmulationManager],
"_fileChooserInterceptors": [Set],
"_frameManager": [FrameManager],
"_javascriptEnabled": true,
"_keyboard": [Keyboard],
"_mouse": [Mouse],
"_pageBindings": [Map],
"_screenshotTaskQueue": [ScreenshotTaskQueue],
"_target": [Target],
"_timeoutSettings": [TimeoutSettings],
"_touchscreen": [Touchscreen],
"_tracing": [Tracing],
"_viewport": [Object],
"_workers": [Map],
"emitter": [Object],
"eventsMap": [Map]
},
"_remoteObject": {
"className": "HTMLDivElement",
"description": "div.block-editor-link-control__search-item.is-current",
"objectId": "-193265238525024879.17.113",
"subtype": "node",
"type": "object"
}
}
This actually has a possible culprit of a solution, but what is the right way of testing for this (instead of toBeInTheDocument())?
It looks like you are missing an await inside of the expect block, since findByLabelText returns a promise:
expect(
await findByLabelText($document, 'Currently selected', {
exact: false,
})
).toBeInTheDocument();

React, Hardhat frontend smart contract method calling, how to do so?

I'm using hardhat locally and have a react frontend up and running but I can't call the methods without errors.
I've tried both ethers.js and web3.
Here's my code and attempts. Please let me know if you see what I'm doing wrong.
I'm trying to interact with contracts that are deployed in the local hardhat env through web3
I'm unable to get back the data from the contract, here's the info
I have:
var list = await contract.methods.getList();
console.log("list ", list );
which gets me
list {arguments: Array(0), call: ƒ, send: ƒ, encodeABI: ƒ, estimateGas: ƒ, …}
When I do
var list = await contract.methods.getList().call();
console.log("list ", list );
I get this error in the browser:
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.
I do:
Setup in console:
npx hardhat node
>Started HTTP and WebSocket JSON-RPC server at http://127.0.0.1:8545/
>Accounts
>========
>...
npx hardhat compile
> Nothing to compile
npx hardhat run scripts/deploy.js --network hardhat
Note: In the deploy.js file, I do a
const list = await contract.getList();
console.log("list", list ); // correctly outputs ["string", "string"]
The method:
mapping(uint256 => address) internal list;
uint256 internal listCount;
function getList() public override view returns (address[] memory) {
address[] memory assets = new address[](listCount);
for (uint256 i = 0; i < listCount; i++) {
assets[i] = list[i];
}
return assets;
}
In react App.js:
import Contract_from './data/abi/Contract_.json'; // Contract_ is a placer
var contract = new web3.eth.Contract(Contract_, address_given_on_deploy);
var contractAddress = await contract .options.address; // correctly outputs
var list= await contract.methods.getList().call();
console.log("list", list);
As you see, this doesn't return the values from the method. What am I doing wrong here?
For any reason and may be likely the issue, here's my config:
require("#nomiclabs/hardhat-waffle");
// openzeppelin adds
require("#nomiclabs/hardhat-ethers");
require('#openzeppelin/hardhat-upgrades');
//abi
require('hardhat-abi-exporter');
// This is a sample Hardhat task. To learn how to create your own go to
// https://hardhat.org/guides/create-task.html
task("accounts", "Prints the list of accounts", async () => {
const accounts = await ethers.getSigners();
for (const account of accounts) {
console.log(account.address);
}
});
// You need to export an object to set up your config
// Go to https://hardhat.org/config/ to learn more
/**
* #type import('hardhat/config').HardhatUserConfig
*/
module.exports = {
networks: {
hardhat: {
gas: 12000000,
blockGasLimit: 0x1fffffffffffff,
allowUnlimitedContractSize: true,
timeout: 1800000,
chainId: 1337
}
},
solidity: {
compilers: [
{
version: "0.8.0",
settings: {
optimizer: {
enabled: true,
runs: 1000
}
}
},
{
version: "0.8.2",
settings: {
optimizer: {
enabled: true,
runs: 1000
}
}
},
],
},
abiExporter: {
path: './frontend/src/data/abi',
clear: true,
flat: true,
only: [],
spacing: 2
}
}
__
I thought maybe i would try ethers.js since that is what i do my testing in but same issue.
For whatever reason, I can "get" the contracts, print the methods that belong to them, but I can't actually call the methods.
Here's my ethers.js brevity:
provider = new ethers.providers.Web3Provider(window.ethereum);
if(provider != null){
const _contract = new ethers.Contract(address, _Contract, provider);
var list= await _contract.getList().call();
console.log("list", list);
}
The error i get from this is:
Error: call revert exception (method="getList()", errorArgs=null, errorName=null, errorSignature=null, reason=null, code=CALL_EXCEPTION, version=abi/5.4.0)
I've tried numerous contracts in the protocol and same thing for each

How to use JWT to store data in NextAuth

I return the following JSON after confirming credentials:
{username: 'foo', name: 'bar', type: 123}
However, NextAuth does not allow me to store all the fields due to model limitations, so what it returns in JWT to client is:
{name: 'bar', email: null, image: null}
My [...nextauth].js setup is very basic:
providers: [
Providers.Credentials({
async authorize(credentials) {
const res = await fetch('http://localhost:3000/api/user', {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'credentials': JSON.stringify(credentials)
}
})
const user = await res.json()
if (user && !user.message) {
return user
} else {
return null
}
}
})
],
The only solution I came up with is to fake email field with JSON string in which I can store everything I need:
{name: 'bar', email: "{username: 'foo', type: 123}", image: null}
How can I do it properly? I tried looking into custom models (https://next-auth.js.org/tutorials/typeorm-custom-models), but it seems to be only about databases, which is not my case since I use JWT for session storage.
Also what drawbacks I can encounter if I continue with my solution?
You will need to persist the additional info through callbacks, at first through JWT's callback and then Session's callback:
callbacks: {
async jwt(token, user, account, profile, isNewUser) {
// Since you are using Credentials' provider, the data you're persisting
// _should_ reside in the user here (as far as can I see, since I've just tested it out).
// This gets called whenever a JSON Web Token is created (once) or updated
if (user?.type) {
token.status = user.type
}
if (user?.username) {
token.username = user.username;
}
return token
},
async session(session, token) {
session.type = token.type;
session.username = token.username;
return session
}
}

Switch Metamask Network to chain 1 (Ethereum Mainnet)

This past week Metamask introduced a new function called "wallet_addEthereumChain" which allows the user to automatically add a new Etheruem RPC to their wallet when prompted. This function also allows the user to change the network they are connected to, for example, if I already have Binance Smart Chain connected to metamask, calling wallet_addEthereumChain changes the active network to BSC. However, when trying this for the Ethereum chain, it gives an error that you cannot add mainnet RPC.
I have used the following code to change to change from Ethereum Mainnet to Binance Smart Chain, and it works fine:
switchToBinance: async function () {
let ethereum = window.ethereum;
const data = [{
chainId: '0x38',
chainName: 'Binance Smart Chain',
nativeCurrency:
{
name: 'BNB',
symbol: 'BNB',
decimals: 18
},
rpcUrls: ['https://bsc-dataseed.binance.org/'],
blockExplorerUrls: ['https://bscscan.com/'],
}]
/* eslint-disable */
const tx = await ethereum.request({method: 'wallet_addEthereumChain', params:data}).catch()
if (tx) {
console.log(tx)
}
},
However when I try the Exact thing, metamask throws an exception saying I cannot add a mainnet RPC:
switchToEthereum: async function () {
let ethereum = window.ethereum;
const data = [{
chainId: '0x1',
chainName: 'Ethereum',
nativeCurrency: {
name: 'Ethereum',
symbol: 'ETH',
decimals: 18,
},
rpcUrls: ['https://mainnet.infura.io/v3/undefined'],
blockExplorerUrls: ['https://etherscan.io'],
}]
/* eslint-disable */
const tx = await ethereum.request({method: 'wallet_addEthereumChain', params:data}).catch()
if (tx) {
console.log(tx)
}
},
However, the request for adding a new RPC connection, and changing the active RPC connection is the same. So is there a way to change the active Ethereum provider from a custom chain to Mainnet (chain ID-1)
as this issue comment point, for security reason wallet_addEthereumChain not support mainnet. But there a new EIP to resolve this issue, follow EIP-3326 to find release info, and this discuss to see draft progrss.
chainId: '0x38' // error because await not decimal
Number('0x38').toString(10) //56 - chain ID of BSC
Right:
chainId: `0x${Number(56).toString(16)}`
OR:
chainId: `0x86`
Simply you have to prefix 0x with the chainId.
Example:
await ethereum.request({
method: 'wallet_switchEthereumChain',
params: [{ chainId: '0x1' }],
})

the tx doesn't have the correct nonce. account has nonce of: 5 tx has nonce of: 15

Using truffle (3.4.6), metamask (3.9.2) and testrpc (4.0.1), I call a transaction and get "Error: the tx doesn't have the correct nonce. account has nonce of: 5 tx has nonce of: 15". I have cut down the body of my contract method to something trivial and I still get this. Any idea what causes it?
contract MyContract {
mapping (address => bool) authorized;
function myMethod (uint element, uint price) whenNotPaused returns (bool) {
if (!authorized[msg.sender]) throw;
return true;
}
}
I call the method like this (using truffle):
MyContract.deployed().then((instance) => {
instance.myMethod (id, price, {from: account}).then (...)
In this thread i saw a suggestion of switching networks back and forth and the error self correcting.
¯\_(ツ)_/¯
#okwme is right, but you can also change your configuration of the network to fix the issue. Assume you're running a dev network on localhost with a HDWallet provider, then you can fix the error by commenting out that config property and add host and port properties to it.
It looks like follows:
development: {
host: "127.0.0.1",
port: 8545,
network_id: "*",
gas: 6721975
// networkCheckTimeout: 10000,
// provider: function() {
// return new HDWalletProvider(mnemonic, 'http://127.0.0.1:8545/', 0, 10);
// },
// network_id: '*',
// gas: 6721975,
},
},