Await Keeps on Waiting - React, React Router - javascript

I am using Truffle React Box. When I use React Router to open a component. Await in ComponentDidMount doesn't return anything. However, after refreshing page, it works fine.
This is my code:
componentDidMount = async () => {
try {
console.log("1");
const web3 = await getWeb3();
console.log("2")
const accounts = await web3.eth.getAccounts();
const Contract = truffleContract(PrototypeStateContract);
Contract.setProvider(web3.currentProvider);
const instance = await Contract.deployed();
this.setState({ web3, accounts, contract: instance });
} catch (error) {
alert(
`Failed to load web3, accounts, or contract. Check console for details.`
);
console.log(error);
}
};
When using react router "Link to" to access a component, only "1" gets printed.
When refreshing the same page, both "1" and "2" gets printed as expected.
How can I solve this?

The problem is resolved after making these changes to getWeb3.js.
import Web3 from "web3";
const getWeb3 = () =>
new Promise( async(resolve, reject) => {
// Wait for loading completion to avoid race conditions with web3 injection timing.
// Modern dapp browsers...
if (window.ethereum) {
const web3 = new Web3(window.ethereum);
try {
// Request account access if needed
await window.ethereum.enable();
// Acccounts now exposed
resolve(web3);
} catch (error) {
reject(error);
}
}
// Legacy dapp browsers...
else if (window.web3) {
// Use Mist/MetaMask's provider.
const web3 = window.web3;
console.log("Injected web3 detected.");
resolve(web3);
}
// Fallback to localhost; use dev console port by default...
else {
const provider = new Web3.providers.HttpProvider(
"http://127.0.0.1:9545"
);
const web3 = new Web3(provider);
console.log("No web3 instance injected, using Local web3.");
resolve(web3);
}
});
export default getWeb3;
I have removed the event listener as window doesn't load when accessing from react-router Link.

Related

How to handle web3JS without using external wallets

I wanted to use web3JS config without using external wallets like metamask. To handle automated functions using cron jobs which are supposed to run every week. Since metamask asks for permission to use send() method to remove that I wanted to use a account where I will upload private key and stuff. I got this code from internet it works for locally/browser wallets dont know where to edit.
import Web3 from "web3";
const getWeb3 = () =>
new Promise((resolve, reject) => {
// Wait for loading completion to avoid race conditions with web3 injection timing.
window.addEventListener("load", async () => {
// Modern dapp browsers...
if (window.ethereum) {
const web3 = new Web3(window.ethereum);
try {
// Request account access if needed
await window.ethereum.enable();
// Accounts now exposed
resolve(web3);
console.log("enabled", web3);
console.log("MetaMask injected");
} catch (error) {
reject(error);
}
}
// Legacy dapp browsers...
else if (window.web3) {
// Use Mist/MetaMask's provider.
const web3 = window.web3;
// const web3 = window.web3.currentProvider.enable();
console.log("Injected web3 detected.");
resolve(web3);
}
// Fallback to localhost; use dev console port by default...
else {
const provider = new Web3.providers.HttpProvider(
"http://127.0.0.1:7545"
);
const web3 = new Web3(provider);
console.log("No web3 instance injected, using Local web3.");
resolve(web3);
}
});
});
export default getWeb3;
solved it
const Web3 = require("web3");
const WalletProvider = require("#truffle/hdwallet-provider");
let provider = new WalletProvider({
mnemonic: {
phrase:
"*******",
},
providerOrUrl: "https://goerli.infura.io/v3/****************",
});
const web3 = new Web3(provider);
const fetch123 = async () => {
const accounts = await web3.eth.getAccounts();
console.log(accounts);
};
fetch123();

Uncaught (in promise) ReferenceError: Buffer is not defined. Using Phantom Wallet, Solana and React to make a transaction

I created a simple CRA app to figure out how to use the Phantom wallet to make Solana transactions(I still don't know If that is even possible). I referenced two Stackoverflow questions source and source and came up with a somewhat working code as in the airdrop is working perfectly fine but the main transaction is not.
This is my code:
import "./App.css";
import { useEffect, useState } from "react";
const web3 = require("#solana/web3.js");
function App() {
const [provider, setProvider] = useState(null);
const [walletKey, setWalletKey] = useState(null);
const getProvider = () => {
if ("solana" in window) {
const provider = window.solana;
if (provider.isPhantom) {
return provider;
}
}
};
const connectWallet = async () => {
const provider = getProvider();
if (provider) {
try {
const response = await provider.connect();
const pubKey = await provider.publicKey;
console.log(pubKey);
setProvider(provider);
setWalletKey(response.publicKey.toString());
} catch (err) {
// { code: 4001, message: 'User rejected the request.' }
}
}
};
useEffect(() => connectWallet, []);
const airDropSol = async (connection, publicKey) => {
try {
const airdropSignature = await connection.requestAirdrop(
publicKey,
web3.LAMPORTS_PER_SOL
);
const latestBlockHash = await connection.getLatestBlockhash();
// Confirming that the airdrop went through
await connection.confirmTransaction({
blockhash: latestBlockHash.blockhash,
lastValidBlockHeight: latestBlockHash.lastValidBlockHeight,
signature: airdropSignature,
});
console.log("Airdropped");
} catch (error) {
console.error(error);
}
};
async function transferSOL() {
//Changes are only here, in the beginning
const phantomProvider = provider;
if (!phantomProvider) {
console.log("No provider found", phantomProvider);
}
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(
"Wallet Key I want to send SOL to here"
);
// Airdrop some SOL to the sender's wallet, so that it can handle the txn fee
airDropSol(connection, pubKey);
console.log("WORKED 1");
const transaction = new web3.Transaction();
const instructions = web3.SystemProgram.transfer({
fromPubkey: pubKey,
toPubkey: recieverWallet,
lamports: web3.LAMPORTS_PER_SOL, //Investing 1 SOL. Remember 1 Lamport = 10^-9 SOL.
});
transaction.add(instructions);
console.log("WORKED 2");
// Setting the variables for the transaction
transaction.feePayer = pubKey;
let blockhashObj = await connection.getLatestBlockhash();
transaction.recentBlockhash = blockhashObj.blockhash;
const signature = await phantomProvider.signAndSendTransaction(
connection,
transaction,
[pubKey]
);
await connection.confirmTransaction(signature);
console.log(signature);
}
return (
<div className="App">
<header className="App-header">
<h2>Tutorial: Connect to Phantom Wallet</h2>
{provider && walletKey && <p>Connected account {walletKey}</p>}
{provider && walletKey && <button onClick={transferSOL}>TEST</button>}
{!provider && (
<p>
No provider found. Install{" "}
Phantom Browser extension
</p>
)}
</header>
</div>
);
}
export default App;
This is the error generated in and I don't know how to fix it. Can anyone help? Error in browser console
Also when I run npm start this error in vcode console also gets shown.
All I want to do is simply send SOL from one phantom wallet to another like sending money in real life, I have spent alot of time trying to figure this out someone please point out the problem and help
Use #solana/web3.js version 1.30.2
New versions form web3 libraries need some dependencies and webpack configurations.
You can use a code I'm sharing:-
Refer my code on this link
With Webpack 5 you need to polyfill Buffer.
Here is a tutorial on how to do so https://viglucci.io/how-to-polyfill-buffer-with-webpack-5
And here is an example of a webpack config of a Solana dApp UI made with CRA https://github.com/Bonfida/serverless-merch/blob/master/ui/config-overrides.js

Non-Ethereum browser detected. You should consider trying MetaMask

Im having a simple UI where i need a metamask connect button
but when i use this code i keep getting the
"Non-Ethereum browser detected. You should consider trying MetaMask!" error even though i have metamsk up an running in my browser
This is the code here:
window.addEventListener('load', async () => {
// Modern dapp browsers...
if (window.ethereum) {
window.web3 = new Web3(ethereum);
try {
await ethereum.enable();
var accounts= await web3.eth.getAccounts();
var option={from: accounts[0] };
} catch (error) {
// User denied account access...
}
}
// Legacy dapp browsers...
else if (window.web3) {
window.web3 = new Web3(web3.currentProvider);
// Acccounts always exposed
web3.eth.sendTransaction({/* ... */});
}
// Non-dapp browsers...
else {
console.log('Non-Ethereum browser detected. You should consider trying MetaMask!');
}
const ethereumButton = document.querySelector('.enableEthereumButton');
const showAccount = document.querySelector('.showAccount');
ethereumButton.addEventListener('click', () => {
getAccount();
});
async function getAccount() {
const accounts = await ethereum.request({ method: 'eth_requestAccounts' });
const account = accounts[0];
showAccount.innerHTML = account;
};
and this are the 2 buttons for account and to connect
<button class="enableEthereumButton">Enable Ethereum</button>
<h2>Account: <span class="showAccount"></span></h2>
What do I need to do to make this work, i followed the metamask tutorial but they are written so bad, they are almost useless
You dont need to use window for metamask access. You can try replacing your if with somthing like this.
if (window.ethereum) {
const web3 = new Web3(ethereum);
try {
await ethereum.enable();
var accounts = await web3.eth.getAccounts();
console.log(accounts)
} catch (error) {
// User denied account access...
}
}
The getAccount() function isn't neccesary as you should be able to pull everything from the web3.eth.* anyway.

Web3 error: Duplicated method constructor. This method is defined as RPC call and as Object method

Having the following issue when deploying my web3 inside of VueX:
TypeError: Duplicated method constructor. This method is defined as RPC call and as Object method.
I have deduced that the issue is in the declaration of web3 in setupWeb3 Action (see below).
I am assuming it is some typing issue?
I am declaring a global namespace in my main.ts as follows:
declare global {
interface Window {
ethereum:any;
web3:any;
}
}
Here are my Actions:
export const actions: ActionTree<Network, RootState> = {
setupWeb3(context: ActionContext<Network, RootState>) {
let web3;
if (window.ethereum) {
web3 = new Web3(window.ethereum);
window.ethereum.enable().then(enabled => console.log(enabled));
} else if (window.web3) {
web3 = new Web3(window.web3.currentProvider);
} else {
// TODO better handle of metamask
window.alert(
'Non-Ethereum browser detected. You should consider trying MetaMask!',
);
}
context.commit('SET_WEB3', web3);
},
async getNetworkData(context: ActionContext<Network, RootState>) {
const { Web3 } = context.getters;
const network = await Web3.eth.net.getNetworkType();
const networkId = await Web3.eth.net.getId();
const currentBlock = await Web3.eth.getBlockNumber();
context.commit('SET_NETWORK_DATA', {
network,
networkId,
currentBlock,
});
},
getAddress(context: ActionContext<Network, RootState>) {
const { Web3 } = context.getters;
Web3.eth.getAccounts().then((account: string[]) =>
context.commit("SET_ADDRESS", account[0]));
},
bootstrapContracts(context: ActionContext<Network, RootState>) {
const setupWeb3 = context.dispatch('setupWeb3');
const network = context.dispatch('getNetworkData');
const address = context.dispatch('getAddress');
Promise.all([setupWeb3, network, address,])
.then(() => {
context.dispatch('setupLootControls');
});
},
};
Turns out that I was on a beta release and by upgrading to
"web3": "^1.2.9"
Fixed the error for me.

Web3: No provider set

I'm writing a script using web3 (1.0.0-beta.27), where I'm trying to deploy a contract and listen for an event.
Here's the simplified version of the code:
const Web3 = require('web3');
let web3 = new Web3('http://localhost:8545');
let MyContract = new web3.eth.Contract(abi);
let accounts = await web3.eth.getAccounts();
let contract = await MyContract.deploy({data: code})
.send({from: accounts[0], gas: 1000000});
contract.events.MyEvent((error, result) => {
if (error) {
return console.error(error);
}
}
However, when I run the code, I get the following error:
Error: No provider set.
at Subscription.subscribe (/node_modules/web3-core-subscriptions/src/subscription.js:199:20)
at Contract._on (/node_modules/web3-eth-contract/src/index.js:634:18)
My understanding was that passing the URL to the Web3 constructor would set the provider, but that doesn't seem to be working.
You need to pass in an HttpProvider when creating Web3. Change
let web3 = new Web3('http://localhost:8545');
to
let web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545'));
or, you can set the provider after creating Web3:
const web3 = new Web3();
web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545'));

Categories

Resources